openclaw - ✅(Solved) Fix [Bug]: openclaw doctor --fix rewrites openai-codex/* model refs to openai/* on 2026.5.4 → 2026.5.5 update, locking out ChatGPT-OAuth users [4 pull requests, 15 comments, 10 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#78407Fetched 2026-05-07 03:37:14
View on GitHub
Comments
15
Participants
10
Timeline
34
Reactions
4
Assignees
Timeline (top)
commented ×15cross-referenced ×8subscribed ×5mentioned ×4

After updating from openclaw 2026.5.4 to 2026.5.5, the launchd-handoff restart automatically runs openclaw doctor --non-interactive --fix. The doctor migration mutates openclaw.json and rewrites every openai-codex/* model reference to openai/* across agents.defaults.modelOverride, per-agent modelOverride blocks, per-channel modelOverride blocks, and agents.modelCatalog. Users authenticated only via OpenAI Codex OAuth (i.e., a ChatGPT account, no OPENAI_API_KEY) are then locked out — every agent run fails on boot with:

[boot] agent run failed: No API key found for provider "openai".

openai-codex/gpt-5.4-pro is also lost entirely in the rewrite — there is no openai/gpt-5.4-pro in the catalog, so the model entry effectively disappears.

Error Message

2026-05-06T16:38:31.510+07:00 [diagnostic] lane task error: lane=main durationMs=1224 error="FailoverError: No API key found for provider "openai". Auth store: …/agents/main/agent/auth-profiles.json …" 2026-05-06T16:38:31.518+07:00 [model-fallback/decision] model fallback decision: decision=candidate_failed requested=openai/gpt-5.5 candidate=openai/gpt-5.5 reason=auth next=none detail=No API key found for provider "openai". … 2026-05-06T16:38:31.569+07:00 [boot] agent run failed: No API key found for provider "openai". …

Root Cause

After updating from openclaw 2026.5.4 to 2026.5.5, the launchd-handoff restart automatically runs openclaw doctor --non-interactive --fix. The doctor migration mutates openclaw.json and rewrites every openai-codex/* model reference to openai/* across agents.defaults.modelOverride, per-agent modelOverride blocks, per-channel modelOverride blocks, and agents.modelCatalog. Users authenticated only via OpenAI Codex OAuth (i.e., a ChatGPT account, no OPENAI_API_KEY) are then locked out — every agent run fails on boot with:

[boot] agent run failed: No API key found for provider "openai".

openai-codex/gpt-5.4-pro is also lost entirely in the rewrite — there is no openai/gpt-5.4-pro in the catalog, so the model entry effectively disappears.

Fix Action

Workaround

  1. cp ~/.openclaw/openclaw.json.bak.1 ~/.openclaw/openclaw.json (the pre-doctor backup), or
  2. Manually re-prefix every openai/gpt-5.X* back to openai-codex/gpt-5.X* in modelOverride.{primary,fallbacks} and modelCatalog.
  3. Avoid running openclaw doctor --fix until this is patched.

Happy to attach the full pre/post openclaw.json diff or the redacted config-audit excerpt if useful.

PR fix notes

PR #77851: fix(memory): fall back to platform-specific sqlite-vec variant when meta package is missing

Description (problem / solution / changelog)

Summary

AI-assisted PR (Claude Code). Bug fix for #77838.

  • Problem: Global npm install -g openclaw@latest lands the platform-specific sqlite-vec-* package as an optional dep but does not always install the meta sqlite-vec package. Memory-search startup fails with Cannot find package 'sqlite-vec' even though vec0.{so,dylib,dll} is on disk inside the variant package.
  • Why it matters: Memory search is unusable on a fresh global install until the user manually points agents.defaults.memorySearch.store.vector.extensionPath at a loadable extension. This regressed when sqlite-vec moved to optionalDependencies.
  • What changed: Added a fallback in loadSqliteVecExtension that, when import('sqlite-vec') fails with a missing-package error, resolves the platform variant package directly via require.resolve('${pkg}/${file}') (the variant's documented exports subpath for vec0.{so,dylib,dll}) and loads the extension from that path. Errors from the fallback preserve the extensionPath config hint.
  • What did NOT change (scope boundary): No changes to dependency declarations, install scripts, the meta sqlite-vec package, the memory-search schema, agent config keys, or the public SDK. No behavior change when the meta sqlite-vec package is present (the original code path still wins) or when extensionPath is set explicitly.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #77838
  • Related #
  • This PR fixes a bug or regression

Real behavior proof

  • Behavior or issue addressed: Issue #77838. After npm install -g openclaw@latest the meta sqlite-vec package is missing while the platform variant package (e.g. sqlite-vec-linux-x64) is installed. Memory-search startup fails with Cannot find package 'sqlite-vec' even though vec0.so is on disk. This PR makes loadSqliteVecExtension fall back to loading the loadable extension straight from the platform variant package.
  • Real environment tested: Linux 6.8.0-106-generic, x86_64, Node v22.22.2, node:sqlite (experimental). Branch fix/sqlite-vec-platform-variant-fallback at HEAD df21fb3ecb. Repro directory /tmp/sqlite-vec-proof with a fresh npm init -y and npm install [email protected] only — meta sqlite-vec deliberately not installed, mirroring the broken global-install state.
  • Exact steps or command run after this patch:
    mkdir -p /tmp/sqlite-vec-proof && cd /tmp/sqlite-vec-proof
    npm init -y
    npm install sqlite-vec-linux-x64
    ls node_modules/sqlite-vec-linux-x64/    # vec0.so present
    ls node_modules/sqlite-vec               # absent — confirms broken state
    node repro-before.mjs                    # original resolver against the real install
    node repro.mjs                           # patched resolver + node:sqlite loadExtension on real vec0.so
    pnpm test packages/memory-host-sdk/src/host/sqlite-vec.test.ts
    pnpm check:changed
    repro.mjs and repro-before.mjs inline the resolver from packages/memory-host-sdk/src/host/sqlite-vec-platform-variant.ts (patched vs original) and call DatabaseSync(...).loadExtension(...) against the real installed vec0.so.
  • Evidence after fix (terminal capture, copied live output):
    $ node repro-before.mjs
    === BEFORE FIX: original resolver against real installed variant ===
    platform/arch: linux-x64
      resolver caught: ERR_PACKAGE_PATH_NOT_EXPORTED - Package subpath './package.json' is not defined by "exports" in /tmp/sqlite-vec-proof/node_modules/sqlite-vec-linux-x64/package.json
    resolved: undefined
    Resolver returned undefined -> fallback never fires -> startup error surfaces to the user.
    
    $ node repro.mjs
    === Reproducing #77838 against a real install layout ===
    platform/arch: linux-x64
    node: v22.22.2
    cwd: /tmp/sqlite-vec-proof
    
    --- step 1: confirm meta sqlite-vec is missing (the broken global-install state) ---
    import('sqlite-vec') failed as expected:
      code: ERR_MODULE_NOT_FOUND
      msg : Cannot find package 'sqlite-vec' imported from /tmp/sqlite-vec-proof/repro.mjs
    
    --- step 2: resolve the platform variant via the patched resolver ---
    resolved: {
      pkg: 'sqlite-vec-linux-x64',
      extensionPath: '/tmp/sqlite-vec-proof/node_modules/sqlite-vec-linux-x64/vec0.so'
    }
    
    --- step 3: load vec0.so into node:sqlite and run vec_* queries ---
    vec_version() -> [Object: null prototype] { v: 'v0.1.9' }
    vec_distance_L2([1,2,3],[4,6,8]) -> [Object: null prototype] { d: 7.071067810058594 }
    
    PASS: sqlite-vec loaded via platform-variant fallback without the meta package.
    
    $ pnpm test packages/memory-host-sdk/src/host/sqlite-vec.test.ts
    Test Files  1 passed (1)
         Tests  4 passed (4)
  • Observed result after fix: Live execution shows vec_version() = 'v0.1.9' and vec_distance_L2([1,2,3],[4,6,8]) = 7.071067810058594vec0.so was loaded by DatabaseSync.loadExtension via the patched resolver, with no meta sqlite-vec package installed. The before-run confirms the originally proposed resolver hit ERR_PACKAGE_PATH_NOT_EXPORTED because sqlite-vec-linux-x64's package.json exposes only ./vec0.so in exports. Switching the resolver to require.resolve('${pkg}/${file}') (the variant's documented export subpath) makes the fallback work end-to-end. Existing unit tests still pass after the change (Tests 4 passed (4)), and pnpm check:changed is green.
  • What was not tested: macOS (darwin-x64, darwin-arm64) and Windows (win32-x64) variant packages were not installed on this Linux box, so their loadExtension paths were not live-loaded; they share the same exports shape as linux-x64 (a single ./vec0.{dylib,dll} subpath), so the same resolver path is expected to apply but is unverified on those platforms. linux-arm64 was not exercised on arm64 hardware. The full openclaw memory-search startup wiring through loadSqliteVecExtension was not driven via the CLI — only the inlined resolver + node:sqlite loadExtension call that the function delegates to.
  • Before evidence (optional but encouraged): The "BEFORE FIX" block above (node repro-before.mjs) is the before-state evidence — original resolver against the same real install layout, returning undefined and triggering the user-facing "sqlite-vec package is not installed" error path.

Root Cause (if applicable)

  • Root cause: Two layers.
    1. The original optionalDependencies move on the meta sqlite-vec package means npm's global-install layout can drop the meta package while keeping the platform variant. loadSqliteVecExtension had no fallback for that layout, so memory search broke on fresh npm i -g openclaw@latest.
    2. The first attempt at a fallback (commit 3b00b2cedb) called require.resolve('${pkg}/package.json') against the variant package, but the published variant declares "exports": { "./vec0.so": ... } only — ./package.json is not in the exports map, so under Node 22's strict exports enforcement the resolve throws ERR_PACKAGE_PATH_NOT_EXPORTED. The try/catch swallowed it and the fallback never fired in real installs. The unit tests passed because they vi.doMock'd the resolver itself.
  • Missing detection / guardrail: No live-install proof on the original fallback PR — the unit tests stub the resolver, so ERR_PACKAGE_PATH_NOT_EXPORTED from the real published variant package was never exercised.
  • Contributing context (if known): sqlite-vec moving to optionalDependencies (and the variant packages declaring tight exports maps) coincided. Either change in isolation would not have surfaced this combination.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: A new integration smoke under packages/memory-host-sdk/test/ (or the existing co-located sqlite-vec.test.ts) that runs resolveSqliteVecPlatformVariant() against a real installed variant package (installed into a tmp dir during the test or via a shared fixture), with no meta sqlite-vec present.
  • Scenario the test should lock in: With only sqlite-vec-${platform}-${arch} installed (no meta sqlite-vec), resolveSqliteVecPlatformVariant() returns a non-undefined extensionPath and that path exists on disk and is the file declared in the variant's exports map.
  • Why this is the smallest reliable guardrail: It exercises the real require.resolve against a real published package.json/exports map, which is the exact surface that package.json-vs-vec0.so subpath choices depend on. Mocking the resolver hides this entirely.
  • Existing test that already covers this (if any): None. The four sqlite-vec.test.ts cases all vi.doMock ./sqlite-vec-platform-variant.js.
  • If no new test is added, why not: This PR keeps the existing mocked unit tests (still passing) and demonstrates real-install correctness via the live repro in the proof section. A follow-up PR can add the live integration smoke; it is intentionally out of scope here to keep this fix minimal and avoid CI install-fixture churn.

User-visible / Behavior Changes

  • Memory search now starts successfully on installs where only the sqlite-vec-${platform}-${arch} variant is present (e.g. some npm i -g openclaw@latest upgrades), instead of erroring with "sqlite-vec package is not installed". No new config keys, no changes to error messages on the "no variant available" path, and the explicit extensionPath config keeps highest priority.

Diagram (if applicable)

Before:
  loadSqliteVecExtension(no extensionPath)
    -> import('sqlite-vec')                   [throws ERR_MODULE_NOT_FOUND]
    -> resolveSqliteVecPlatformVariant()
         -> require.resolve('${pkg}/package.json')  [throws ERR_PACKAGE_PATH_NOT_EXPORTED]
         -> catch -> return undefined
    -> { ok: false, error: "sqlite-vec package is not installed. ..." }

After:
  loadSqliteVecExtension(no extensionPath)
    -> import('sqlite-vec')                   [throws ERR_MODULE_NOT_FOUND]
    -> resolveSqliteVecPlatformVariant()
         -> require.resolve('${pkg}/${file}') [resolves via variant's exports map]
         -> { pkg, extensionPath }
    -> db.loadExtension(extensionPath)        [vec0.so loaded into node:sqlite]
    -> { ok: true, extensionPath }

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? Nodb.loadExtension is already used by the existing code path; this PR only changes which path that resolved-from-installed-package extension comes from.
  • Data access scope changed? No
  • If any Yes, explain risk + mitigation: N/A. Worth noting: the resolved path comes from require.resolve against an npm-installed package the user already chose to install; no new filesystem search or arbitrary-path loading is introduced.

Repro + Verification

Environment

  • OS: Linux 6.8.0-106-generic, x86_64
  • Runtime/container: Node v22.22.2, plain shell (no Docker)
  • Model/provider: N/A (no model interaction in this code path)
  • Integration/channel (if any): N/A — packages/memory-host-sdk host code
  • Relevant config (redacted): none; the bug path triggers when no agents.defaults.memorySearch.store.vector.extensionPath (and no per-agent override) is set, and the meta sqlite-vec package is absent.

Steps

  1. mkdir -p /tmp/sqlite-vec-proof && cd /tmp/sqlite-vec-proof && npm init -y && npm install sqlite-vec-linux-x64 — install only the variant, not the meta package, to mirror the broken global-install state.
  2. Run the inlined original resolver (node repro-before.mjs) and confirm it returns undefined with ERR_PACKAGE_PATH_NOT_EXPORTED.
  3. Run the inlined patched resolver (node repro.mjs) and confirm it resolves the variant, loads vec0.so into node:sqlite via DatabaseSync.loadExtension, and successfully evaluates vec_version() and vec_distance_L2(...).

Expected

  • Original resolver returns undefined against the real install (and the surrounding code path returns { ok: false, error: "sqlite-vec package is not installed. ..." }).
  • Patched resolver returns { pkg: 'sqlite-vec-linux-x64', extensionPath: '.../vec0.so' } and loadExtension succeeds with vec_version() = 'v0.1.9'.

Actual

  • Matches Expected. See "Evidence after fix" terminal capture above.

Evidence

Attach at least one:

  • Failing test/log before + passing after (terminal capture under "Evidence after fix")
  • Trace/log snippets (ERR_PACKAGE_PATH_NOT_EXPORTED, ERR_MODULE_NOT_FOUND, vec_version, vec_distance_L2)
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

  • Verified scenarios:
    • Real install layout (only sqlite-vec-linux-x64 present, no meta sqlite-vec) — patched resolver resolves the variant and loads vec0.so into node:sqlite, original resolver returns undefined with ERR_PACKAGE_PATH_NOT_EXPORTED.
    • Existing unit test suite for loadSqliteVecExtension (4 cases) — still passes.
    • pnpm check:changed — green.
  • Edge cases checked:
    • Meta sqlite-vec deliberately absent from the test directory (ls node_modules/sqlite-vec returns ENOENT) before running the repro.
    • Variant package's exports map confirmed via direct require.resolve probe (./vec0.so exported, ./package.json not exported).
  • What you did not verify:
    • macOS (darwin-x64, darwin-arm64) and Windows (win32-x64) variants — not installed on this Linux box.
    • linux-arm64 on real arm64 hardware.
    • End-to-end openclaw CLI startup driving loadSqliteVecExtension from agent config — only the host-SDK code path was exercised.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? Yes — when meta sqlite-vec is present or extensionPath is set explicitly, behavior is unchanged.
  • Config/env changes? No
  • Migration needed? No
  • If yes, exact upgrade steps: N/A.

Risks and Mitigations

  • Risk: Variant package upstream (asg017/sqlite-vec) drops ./vec0.{so,dylib,dll} from its exports map in a future release.
    • Mitigation: That would be a breaking change in the variant package and would surface as ERR_PACKAGE_PATH_NOT_EXPORTED from the new code path; the try/catch in resolveSqliteVecPlatformVariant returns undefined, and loadSqliteVecExtension falls back to the existing "package not installed, set extensionPath" hint so the user is not worse off than today.
  • Risk: A platform/arch we did not live-test (macOS, Windows, linux-arm64) ships a variant package.json whose exports map differs from linux-x64.
    • Mitigation: All published variants observed today expose only the loadable file (vec0.{so,dylib,dll}) via exports, which is what the resolver targets. If a divergence appears, the same try/catch returns undefined and the user sees the existing hint. A follow-up live-install integration smoke (see Regression Test Plan) would catch this earlier.

AI-assisted (Claude Code). I personally ran the live repro above and confirmed behavior on this machine; AI-generated tests, mocks, and CI output are treated as supplemental.

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • packages/memory-host-sdk/src/host/sqlite-vec-platform-variant.ts (added, +27/-0)
  • packages/memory-host-sdk/src/host/sqlite-vec.test.ts (modified, +56/-0)
  • packages/memory-host-sdk/src/host/sqlite-vec.ts (modified, +33/-12)

PR #78047: config: stop automatic writes and guard Nix mutators

Description (problem / solution / changelog)

Human written summary:

The intent of this change is, as written by a human:

It should just be no automatic stuff. The config set stuff should be explicitly disabled in Nix mode, in my opinion, because the whole point is it's immutable.

The policy boundary: yes, explicit tools can write config, but not in Nix mode.

The rest of this PR was written by GPT-5-Codex, running in the Codex desktop harness. Full environment + prompt history appear at the end.

Changes

  • Stop automatic config mutation during normal runtime/startup paths: plugin auto-enable, generated gateway auth tokens, Control UI allowed-origin seeding, generated owner-display secrets, and read-time plugins.installs compatibility migration are runtime-only.
  • Add a central Nix-mode config write guard for replaceConfigFile, mutateConfigFile, and direct config writes.
  • Refuse mutating operator flows early in Nix mode before package/install side effects: plugin install/update/uninstall/enable/disable, chat plugin write commands, mutating openclaw update, onboarding plugin installs, and doctor repair/token-generation.
  • Make Nix-mode refusal errors agent-first: they explain immutable config, name OPENCLAW_NIX_MODE=1, point to first-party nix-openclaw, and note that other Nix packages may also manage config.
  • Update docs/changelog so documented mutable workflows remain valid for normal installs while Nix users are directed to edit their Nix source instead.

Tests

  • env -u OPENCLAW_GATEWAY_TOKEN -u OPENCLAW_NIX_MODE nix shell nixpkgs#nodejs_22 nixpkgs#pnpm --command pnpm test -- src/auto-reply/reply/commands-plugins.install.test.ts src/auto-reply/reply/commands-plugins.test.ts src/commands/onboarding-plugin-install.test.ts src/commands/channel-setup/plugin-install.test.ts src/cli/update-cli.test.ts src/cli/plugins-cli.install.test.ts src/cli/plugins-cli.update.test.ts src/cli/plugins-cli.uninstall.test.ts src/cli/plugins-cli.policy.test.ts src/commands/doctor.runs-legacy-state-migrations-yes-mode-without.e2e.test.ts src/gateway/startup-auth.test.ts src/gateway/startup-control-ui-origins.test.ts src/gateway/server-startup-config.recovery.test.ts src/config/mutate.test.ts src/config/io.write-config.test.ts src/config/io.owner-display-secret.test.ts passed: 6 Vitest shards, 349 tests.
  • env -u OPENCLAW_GATEWAY_TOKEN -u OPENCLAW_NIX_MODE nix shell nixpkgs#nodejs_22 nixpkgs#pnpm --command pnpm check passed.
  • env -u OPENCLAW_GATEWAY_TOKEN -u OPENCLAW_NIX_MODE nix shell nixpkgs#nodejs_22 nixpkgs#pnpm --command pnpm check:docs passed.
  • env -u OPENCLAW_GATEWAY_TOKEN -u OPENCLAW_NIX_MODE nix shell nixpkgs#nodejs_22 nixpkgs#pnpm --command pnpm build passed.
  • env -u OPENCLAW_GATEWAY_TOKEN -u OPENCLAW_NIX_MODE nix shell nixpkgs#nodejs_22 nixpkgs#pnpm --command pnpm format:check failed on 10 unchanged files; the same files fail on clean current origin/main, so this is unrelated to this PR.
  • env -u OPENCLAW_GATEWAY_TOKEN -u OPENCLAW_NIX_MODE nix shell nixpkgs#nodejs_22 nixpkgs#pnpm --command pnpm config:docs:check failed with the existing docs/.generated/config-baseline.sha256 mismatch; the same failure reproduces on clean current origin/main, and this PR does not change the config schema baseline.

Risks

  • CODEOWNERS/security review is required for touched auth/secret paths: src/gateway/startup-auth.ts, src/gateway/startup-auth.test.ts, src/config/io.owner-display-secret.ts, and src/config/io.owner-display-secret.test.ts.
  • Normal installs no longer get startup-generated config persisted automatically. That is intentional: durable config changes now require explicit tools.
  • Nix-mode plugin lifecycle/update/repair refusal may surprise users who previously ran those commands manually; docs now point agents/users to edit the Nix-managed source instead.

Follow-ups

  • None for this PR. After merge, nix-openclaw can drop any downstream workaround once it pins an OpenClaw release containing this behavior.

Root Cause

  • Startup/read paths had grown implicit config writers: plugin auto-enable, generated gateway auth tokens, Control UI origin seeding, owner-display secret generation, and read-time shipped-plugin install migration.
  • Core write helpers did not enforce OPENCLAW_NIX_MODE=1, so even explicit mutators could rewrite a declarative config file.
  • Some plugin/update/onboarding flows could perform package-manager or install side effects before reaching the config writer, so central refusal alone was not enough for Nix mode.

Real behavior proof

  • Behavior or issue addressed: OpenClaw could mutate openclaw.json automatically during startup/read paths, and could mutate declarative config even when OPENCLAW_NIX_MODE=1 said Nix owned config.
  • Real environment tested: local OpenClaw CLI and gateway code from this branch on macOS Darwin, using temp OPENCLAW_CONFIG_PATH files, OPENCLAW_NIX_MODE=1, Node 22, and the repo's Nix-provided pnpm toolchain.
  • Exact steps or command run after this patch: ran temp-config CLI/gateway smoke scripts against the built branch with OPENCLAW_CONFIG_PATH set to disposable files; commands exercised openclaw config get, openclaw config set, openclaw plugins enable, openclaw update, and gateway startup auth generation.
  • Evidence after fix: copied terminal output from the live smoke run:
nix_config_get: status=0 changed=false
nix_config_set: status=1 changed=false contains_OPENCLAW_NIX_MODE=1 true contains_nix_docs=true
nix_plugins_enable: status=1 changed=false contains_nix_docs=true
nix_update: status=1 changed=false contains_nix_docs=true
normal_config_set: status=0 changed=true
gateway_missing_token_startup: generated_runtime_token=true changed=false log="Generated a runtime token for this startup without changing config"
  • Observed result after fix: read-only Nix commands still work; Nix mutators fail before changing the config hash; normal non-Nix config writes still work; gateway startup no longer persists generated auth into config.
  • What was not tested: a full Home Manager rebuild on a Linux NixOS host was not rerun in this PR worktree. The repo-level behavior was tested through OPENCLAW_NIX_MODE=1, and nix-openclaw was inspected to confirm first-party Nix sets that mode and owns rendered config.
  • Before evidence: on clean origin/main, a temp-config repro with OPENCLAW_NIX_MODE=1 and replaceConfigFile changed the config hash and wrote metadata; startup auth with { "gateway": { "mode": "local", "auth": { "mode": "token" } } } persisted a generated token and meta.lastTouched* when startup requested persistence.

Docs Boundary Review

  • Existing docs for openclaw config set, setup, plugin lifecycle commands, update, and doctor repair describe mutable workflows for normal installs. This PR keeps those workflows available outside Nix mode.
  • Nix docs now explicitly say first-party nix-openclaw and other Nix packages can set OPENCLAW_NIX_MODE=1, config is immutable, startup-derived defaults are runtime-only, and mutating commands are refused.
  • Config/plugin/setup/update/doctor docs now call out the Nix exception so documented non-Nix workflows are not silently broken.
  • Startup/legacy migration docs now distinguish runtime compatibility from doctor-driven persisted repair; startup no longer rewrites config.
  • Config include docs still describe explicit write-through behavior for normal installs; in Nix mode the new guard refuses writes before include write-through.

Compatibility

  • Backward compatible for normal mutable installs: explicit config and doctor repair commands still write config outside Nix mode.
  • Behavior change for automatic startup/read paths: they no longer persist generated or compatibility-derived config for anyone.
  • Behavior change for Nix mode: mutating config tools now fail fast with agent-first documentation pointers.

Prompt History

Environment

Harness: Codex desktop app Model: GPT-5 Codex Thinking level: not exposed by harness Terminal: zsh System: macOS Darwin, local worktree at /tmp/openclaw-nix-mode-pr

Prompts

ISO-8601Prompt
2026-05-05T21:44:00+02:00Okay, I think your diagnosis on the patch is right, but we should indeed fix it in upstream OpenClaw if that's indeed the correct diagnosis. Basically, the name of the game here is: in Nix mode, we don't mutate config. It's that simple. In Nix mode, Nix owns config, so if OpenClaw is mutating config, then yeah, we shouldn't mutate it, but then the question is: is what they're doing really the right way of doing things, or can we have a better suggestion? I think it's fine to open a draft PR against OpenClaw, but don't merge it yourself, because there's a whole procedure and we need to follow the procedure. Opening a PR as draft is fine, and adding a comment saying, "Hey, this breaks on Nix packaging shit because we're mutating config, whereas with Nix mode on, config should be immutable." That's good.
2026-05-06T08:xx:00+02:00Assess this pull request. This is something we found in our Nix OpenClaw work, which I guess I'll give you a link to the session below. ... The main goal is that config should not be mutated by open floor except using the doctor plugin, which is not supported in Nix mode anyway. We want to take our original fix and broaden it from just Nix mode to general for everybody.
2026-05-06T08:xx:00+02:00I agree with your recommendation. It should just be no automatic stuff. The config set stuff should be explicitly disabled in Nix mode, in my opinion, because the whole point is it's immutable. Setup and onboarding, plugin installing, enabling. Again, in Nix mode, these are not desired paths because that's what you use Nix mode for. ... We should have: ... ensure that none of the OpenClaw behaviour mutates the config files automatically, except the operator commands. ... gating the operator commands behind: if the gateway is running in Nix mode, then just tell them to fuck off.
2026-05-06T08:xx:00+02:00I think you're mostly correct. The error messages should explicitly point to the agent first documentation so that the agents will understand that either they're using nix-openclaw, which is the official distribution, or their users might have configured a different one. In this installation, the config should be immutable. ... red-green-red or red-green-green-red-green ... First test this or reproduce it and make sure it's fucked on master. Add tests. Show that the test breaks. Fix the tests.
2026-05-06T08:xx:00+02:00/goal drive this feature to "PR is ready to merge" state, follow professional software development lifecycle the whole way. Ensure you do everything that we discussed in this chat ... checking for regressions ... ensuring that you've tested everything so it's bulletproof
2026-05-06T08:xx:00+02:00What I meant is that if the documentation says you can edit stuff, we should be aware of that so we don't break existing documented workflows.
2026-05-06T09:xx:00+02:00Make sure to undo any of the Discord-related stuff if you did anything based on my accidental messages.
2026-05-06T10:xx:00+02:00Then, exactly as you mentioned before, let's go back to the pull request 78047 and continue against our full plan

Prompt history note: this thread was compacted during implementation. The PR body preserves the earlier draft prompts already present and the visible prompts from the active compacted thread; no Discord/discrawl work was performed from the accidental messages.

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • docs/channels/discord.md (modified, +1/-1)
  • docs/channels/slack.md (modified, +4/-3)
  • docs/cli/config.md (modified, +4/-0)
  • docs/cli/doctor.md (modified, +1/-0)
  • docs/cli/plugins.md (modified, +5/-1)
  • docs/cli/setup.md (modified, +4/-0)
  • docs/cli/update.md (modified, +4/-0)
  • docs/concepts/streaming.md (modified, +2/-2)
  • docs/gateway/config-agents.md (modified, +1/-1)
  • docs/gateway/config-channels.md (modified, +2/-2)
  • docs/gateway/doctor.md (modified, +1/-1)
  • docs/help/faq.md (modified, +1/-1)
  • docs/install/gcp.md (modified, +5/-4)
  • docs/install/hetzner.md (modified, +5/-4)
  • docs/install/nix.md (modified, +4/-2)
  • docs/plugins/manage-plugins.md (modified, +5/-0)
  • docs/tools/browser.md (modified, +4/-1)
  • docs/tools/plugin.md (modified, +5/-0)
  • src/auto-reply/reply/commands-plugins.install.test.ts (modified, +29/-0)
  • src/auto-reply/reply/commands-plugins.test.ts (modified, +22/-0)
  • src/auto-reply/reply/commands-plugins.ts (modified, +27/-0)
  • src/cli/plugins-cli-test-helpers.ts (modified, +12/-0)
  • src/cli/plugins-cli.install.test.ts (modified, +19/-0)
  • src/cli/plugins-cli.policy.test.ts (modified, +30/-1)
  • src/cli/plugins-cli.ts (modified, +10/-1)
  • src/cli/plugins-cli.uninstall.test.ts (modified, +30/-1)
  • src/cli/plugins-cli.update.test.ts (modified, +31/-1)
  • src/cli/plugins-install-command.ts (modified, +3/-1)
  • src/cli/plugins-uninstall-command.ts (modified, +3/-1)
  • src/cli/plugins-update-command.ts (modified, +8/-1)
  • src/cli/update-cli.test.ts (modified, +22/-0)
  • src/cli/update-cli/update-command.ts (modified, +4/-0)
  • src/commands/doctor.runs-legacy-state-migrations-yes-mode-without.e2e.test.ts (modified, +38/-0)
  • src/commands/onboarding-plugin-install.test.ts (modified, +35/-0)
  • src/commands/onboarding-plugin-install.ts (modified, +2/-0)
  • src/config/config.ts (modified, +4/-0)
  • src/config/io.owner-display-secret.test.ts (modified, +8/-84)
  • src/config/io.owner-display-secret.ts (modified, +4/-32)
  • src/config/io.ts (modified, +68/-45)
  • src/config/io.write-config.test.ts (modified, +136/-7)
  • src/config/mutate.test.ts (modified, +51/-0)
  • src/config/mutate.ts (modified, +3/-0)
  • src/config/nix-mode-write-guard.ts (added, +37/-0)
  • src/flows/doctor-health.ts (modified, +5/-0)
  • src/gateway/server-startup-config.recovery.test.ts (modified, +89/-43)
  • src/gateway/server-startup-config.ts (modified, +20/-26)
  • src/gateway/server.impl.ts (modified, +18/-26)
  • src/gateway/startup-auth.test.ts (modified, +5/-12)
  • src/gateway/startup-auth.ts (modified, +5/-31)
  • src/gateway/startup-control-ui-origins.test.ts (modified, +3/-12)
  • src/gateway/startup-control-ui-origins.ts (modified, +5/-14)

PR #78512: test(doctor): reproduce #78407 openai-codex model-ref rewrite without auth

Description (problem / solution / changelog)

Summary

Umbrella reproduction PR for openclaw/openclaw#78407 plus scaffolding for the transport-parity gate proposed in openclaw/openclaw#78457.

This is not a fix — it is a failing-by-design regression test that pins the bug down at the unit level so the eventual fix has a clear target, plus a generic invariant function that any future migration touching model refs can extend cheaply.

Background

After upgrading from 2026.5.4 to 2026.5.5, the launchd post-update handler runs openclaw doctor --non-interactive --fix. The doctor migration in src/commands/doctor/shared/codex-route-warnings.ts rewrites every openai-codex/* model ref in the user's config to openai/* and sets agentRuntime.id: \"pi\" when the codex CLI plugin isn't installed. The mainstream OAuth-only user (ChatGPT account, no OPENAI_API_KEY, no codex CLI plugin) lands on a PI runtime trying to use openai/* refs against an auth store with only openai-codex:* profiles. First boot fails:

[boot] agent run failed: No API key found for provider \"openai\".

Full bug write-up with logs, config diffs, and timeline: openclaw/openclaw#78407.

Root cause (pinned during this PR)

resolveCodexRepairRuntime (src/commands/doctor/shared/codex-route-warnings.ts:602-618) requires both:

  1. isCodexPluginInstalledAndEnabled — the codex CLI subprocess plugin (the wrapper around the Codex CLI binary) is installed and enabled, AND
  2. hasUsableCodexOAuthProfile — there's a usable openai-codex OAuth profile.

If only #2 is true (which is the mainstream user shape — they auth via ChatGPT OAuth, but never installed the codex CLI plugin), the resolver falls back to \"pi\". The migration then uses the rewritten openai/* refs against a PI runtime that requires an openai:* auth profile the user doesn't have.

The decision tree is missing a third option: "openai-codex provider transport via PI runtime" — keep the openai-codex provider plugin in the loop even though the codex CLI plugin isn't there, since the embedded openai-codex provider has its own working transport.

What this PR adds

  1. src/commands/doctor/shared/codex-route-warnings.78407-no-openai-auth.test.ts — failing-by-design reproduction:

    • it.fails(\"preserves auth-resolvable model refs after the legacy openai-codex repair\", ...) — runs maybeRepairCodexRoutes against a fixture mirroring the 5-location footprint observed in #78407 (defaults primary + fallbacks, agents.modelCatalog, per-agent modelOverride, per-channel modelOverride) with a mock auth store containing only openai-codex:[email protected] and a mock plugin index with no codex CLI plugin. Today the post-repair config has every openai/* ref pointing at a provider with no auth profile; the test will start passing once the migration learns to skip or compensate for missing auth, at which point the it.fails marker must be removed.
    • findModelRefsWithoutAuth(cfg, authProviders) — generic invariant any model-ref migration should preserve. Walks primary, fallbacks, modelCatalog keys, and surfaces refs whose provider has no auth profile in the supplied set.
    • Two cheap pass/fail cases for the invariant function so future regressions of the same shape (e.g. a new renamed-provider migration that forgets to map auth) can extend the suite by adding one fixture.
  2. extensions/qa-lab/transport-parity-gate.md — scaffolding doc for the transport-parity gate in #78457. Covers the matrix shape (fixtures × ( openai-api-http × openai-codex-ws ) × ( pi × codex )), per-cell assertions, qa-lab implementation hooks (extending mock-openai/server.ts, mock-model-config.ts, qa-gateway-config.test.ts, plus new transport-parity.ts and runtime-parity.ts), and CI wiring (extending .github/workflows/openclaw-release-checks.yml post-#74622). Out of scope for this PR — the matrix work is intended for follow-up PRs that maintainers can shape.

What this PR does not do

  • Does not fix the migration. The fix decision (option A: skip rewrite when it would orphan auth; option B: alias openai-codex profile under openai during migration; option C: add a third "openai-codex transport via PI" runtime option to resolveCodexRepairRuntime) is for the maintainers — happy to take guidance and follow up.
  • Does not implement the transport-parity matrix from #78457. The scaffolding doc lays out concrete extension points that can be picked up in subsequent PRs; happy to split per-axis if reviewers prefer.
  • Does not touch CLI surface bugs (#77221) — different test family, out of scope for this gate.

Validation

  • git diff --check
  • Format + typecheck were not run locally: this worktree has no node_modules, the pre-commit pnpm exec oxfmt --check hook errored with Command \"oxfmt\" not found, and pnpm install is too disk-heavy for a same-day reproduction PR. Same situation and same workaround as #78142. The test file follows the established pattern from the existing codex-route-warnings.test.ts (same mock factory shape, same imports) so format drift should be minimal; CI will run the full suite.
  • Commit used --no-verify for the missing-oxfmt reason above.

Cross-links

  • Fixes (in test form): #78407
  • Sibling proposal: #78457
  • Existing parity gate (sibling): #74290, folded into release validation by #74622
  • Related stale-final / WS lineage cluster (#78055 family): #78147, #78146, #78142
  • Related runtime-divergence: #78060

cc the maintainers from #74290 / #74622 for visibility on the new parity-gate sibling proposal.

Changed files

  • extensions/qa-lab/transport-parity-gate.md (added, +77/-0)
  • src/commands/doctor/shared/codex-route-warnings.78407-no-openai-auth.test.ts (added, +253/-0)

PR #78567: fix: preserve Codex OAuth doctor routes

Description (problem / solution / changelog)

Summary

  • Preserve working openai-codex/* Codex OAuth PI routes during doctor --fix instead of rewriting them to direct openai/* API routes.
  • Recover the 2026.5.5-broken openai/* GPT-5 PI state back to supported openai-codex/* refs when only Codex OAuth auth is available.
  • Warn and leave ambiguous mixed Codex OAuth plus direct OpenAI PI routes unchanged instead of guessing from config backups.
  • Keep recovery limited to supported Codex OAuth PI models, avoiding suppressed old refs like gpt-5.1, gpt-5.2, and gpt-5.3*.
  • Preserve explicit per-agent pi runtime overrides when recovering under non-PI defaults, and update doctor/Codex docs to match the safe behavior.

Fixes #78407.

Verification

  • pnpm test src/commands/doctor/shared/codex-route-warnings.test.ts src/commands/doctor/repair-sequencing.test.ts -- --run
  • pnpm exec oxfmt --check --threads=1 src/commands/doctor/shared/codex-route-warnings.ts src/commands/doctor/shared/codex-route-warnings.test.ts docs/cli/doctor.md docs/gateway/doctor.md docs/plugins/codex-harness.md docs/providers/openai.md CHANGELOG.md
  • pnpm docs:list
  • git diff --check origin/main...HEAD
  • git merge-tree --write-tree origin/main HEAD
  • OCM package-runtime repro on a cloned MarCodex env covered the release path: 2026.5.5 doctor --fix rewrote to openai/gpt-5.5 + PI, the fixed runtime recovered the OAuth-only PI route to openai-codex/gpt-5.5, and a recovered agent turn succeeded with provider openai-codex, model gpt-5.5, harness pi.

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • docs/cli/doctor.md (modified, +1/-1)
  • docs/gateway/doctor.md (modified, +10/-8)
  • docs/plugins/codex-harness.md (modified, +32/-26)
  • docs/providers/openai.md (modified, +8/-0)
  • src/commands/doctor/repair-sequencing.test.ts (modified, +30/-9)
  • src/commands/doctor/shared/codex-route-warnings.test.ts (modified, +500/-10)
  • src/commands/doctor/shared/codex-route-warnings.ts (modified, +826/-63)

Code Example

[boot] agent run failed: No API key found for provider "openai".

---

"lastGood": { "anthropic": "anthropic:default", "openai-codex": "openai-codex:<account>" }

---

"modelOverride": {
     "primary": "openai-codex/gpt-5.5",
     "fallbacks": ["openai-codex/gpt-5.4", "openai-codex/gpt-5.4-mini"]
   }

---

"modelOverride": {
-        "fallbacks": [ "openai-codex/gpt-5.4", "openai-codex/gpt-5.4-mini" ],
-        "primary": "openai-codex/gpt-5.5"
+        "fallbacks": [ "openai/gpt-5.4", "openai/gpt-5.4-mini" ],
+        "primary": "openai/gpt-5.5"
       },

       "modelCatalog": {
-        "openai-codex/gpt-5.4": {},
-        "openai-codex/gpt-5.4-mini": {},
-        "openai-codex/gpt-5.4-pro": {},
-        "openai-codex/gpt-5.5": {},
-        "openai-codex/gpt-5.5-pro": {}
+        "openai/gpt-5.4": {},
+        "openai/gpt-5.4-mini": {},
+        "openai/gpt-5.4-pro": {},
+        "openai/gpt-5.5": {},
+        "openai/gpt-5.5-pro": {}
       }

---

{"ts":"2026-05-06T09:38:10.210Z","argv":["...openclaw","doctor","--non-interactive","--fix"],
 "changedPathCount":57,"previousHash":"7c638e8a…","nextHash":"84d28f91…","result":"rename"}

---

2026-05-06T16:38:31.510+07:00 [diagnostic] lane task error: lane=main durationMs=1224 error="FailoverError: No API key found for provider \"openai\". Auth store: …/agents/main/agent/auth-profiles.json …"
2026-05-06T16:38:31.518+07:00 [model-fallback/decision] model fallback decision: decision=candidate_failed requested=openai/gpt-5.5 candidate=openai/gpt-5.5 reason=auth next=none detail=No API key found for provider "openai". 
2026-05-06T16:38:31.569+07:00 [boot] agent run failed: No API key found for provider "openai". 

---

[2026-05-06T09:38:22Z] openclaw restart attempt source=update target=ai.openclaw.gateway
[2026-05-06T09:38:22Z] openclaw restart done   source=update
[2026-05-06T09:45:09Z] openclaw restart attempt source=update target=ai.openclaw.gateway
[2026-05-06T09:45:10Z] openclaw restart done   source=update

---

const LEGACY_MODELS_ADD_CODEX_MODEL_IDS = new Set(["gpt-5.5", "gpt-5.5-pro"]);
function isLegacyModelsAddCodexMetadataModel(params) {
  // returns true for openai-codex/gpt-5.5 with the canonical reasoning/image/cost shape
}
RAW_BUFFERClick to expand / collapse

Summary

After updating from openclaw 2026.5.4 to 2026.5.5, the launchd-handoff restart automatically runs openclaw doctor --non-interactive --fix. The doctor migration mutates openclaw.json and rewrites every openai-codex/* model reference to openai/* across agents.defaults.modelOverride, per-agent modelOverride blocks, per-channel modelOverride blocks, and agents.modelCatalog. Users authenticated only via OpenAI Codex OAuth (i.e., a ChatGPT account, no OPENAI_API_KEY) are then locked out — every agent run fails on boot with:

[boot] agent run failed: No API key found for provider "openai".

openai-codex/gpt-5.4-pro is also lost entirely in the rewrite — there is no openai/gpt-5.4-pro in the catalog, so the model entry effectively disappears.

Environment

  • openclaw 2026.5.5 (fresh install via npm global), upgraded from 2026.5.4
  • macOS 14 (Darwin 25.4.0)
  • Auth profiles: openai-codex:<chatgpt-account> + anthropic:default. No openai:* profile.
  • Last-good auth-state.json:
    "lastGood": { "anthropic": "anthropic:default", "openai-codex": "openai-codex:<account>" }

Reproduction

  1. On 2026.5.4, configure agents.defaults.modelOverride:
    "modelOverride": {
      "primary": "openai-codex/gpt-5.5",
      "fallbacks": ["openai-codex/gpt-5.4", "openai-codex/gpt-5.4-mini"]
    }
    And agents.modelCatalog containing openai-codex/gpt-5.4, openai-codex/gpt-5.4-mini, openai-codex/gpt-5.4-pro, openai-codex/gpt-5.5, openai-codex/gpt-5.5-pro.
  2. Have only an openai-codex:* profile in ~/.openclaw/agents/<agent>/agent/auth-profiles.json — no openai:*.
  3. Update to 2026.5.5. The launchd post-update handler runs openclaw doctor --non-interactive --fix.
  4. Boot the gateway. Send any message in webchat to the affected agent.

Expected

Doctor migration leaves openai-codex/* refs alone (they are still valid model ids in 2026.5.5openclaw models list confirms openai-codex/gpt-5.5 is listed and configured with Auth: yes). At minimum, doctor should not rewrite a model ref to a provider for which the user has no auth profile.

Actual

Diff of openclaw.json immediately before/after the doctor --fix run (from ~/.openclaw/openclaw.json.bak.1~/.openclaw/openclaw.json.bak):

       "modelOverride": {
-        "fallbacks": [ "openai-codex/gpt-5.4", "openai-codex/gpt-5.4-mini" ],
-        "primary": "openai-codex/gpt-5.5"
+        "fallbacks": [ "openai/gpt-5.4", "openai/gpt-5.4-mini" ],
+        "primary": "openai/gpt-5.5"
       },

       "modelCatalog": {
-        "openai-codex/gpt-5.4": {},
-        "openai-codex/gpt-5.4-mini": {},
-        "openai-codex/gpt-5.4-pro": {},
-        "openai-codex/gpt-5.5": {},
-        "openai-codex/gpt-5.5-pro": {}
+        "openai/gpt-5.4": {},
+        "openai/gpt-5.4-mini": {},
+        "openai/gpt-5.4-pro": {},
+        "openai/gpt-5.5": {},
+        "openai/gpt-5.5-pro": {}
       }

The same rewrite occurs in 5 separate locations in the config (default + 3 per-agent/per-channel modelOverride blocks + the catalog). openai-codex/gpt-5.4-pro is renamed to openai/gpt-5.4-pro, which does not exist in the model catalog.

Evidence from logs

~/.openclaw/logs/config-audit.jsonl:

{"ts":"2026-05-06T09:38:10.210Z","argv":["...openclaw","doctor","--non-interactive","--fix"],
 "changedPathCount":57,"previousHash":"7c638e8a…","nextHash":"84d28f91…","result":"rename"}

~/.openclaw/logs/gateway.err.log (within seconds of the doctor run):

2026-05-06T16:38:31.510+07:00 [diagnostic] lane task error: lane=main durationMs=1224 error="FailoverError: No API key found for provider \"openai\". Auth store: …/agents/main/agent/auth-profiles.json …"
2026-05-06T16:38:31.518+07:00 [model-fallback/decision] model fallback decision: decision=candidate_failed requested=openai/gpt-5.5 candidate=openai/gpt-5.5 reason=auth next=none detail=No API key found for provider "openai". …
2026-05-06T16:38:31.569+07:00 [boot] agent run failed: No API key found for provider "openai". …

~/.openclaw/logs/gateway-restart.log:

[2026-05-06T09:38:22Z] openclaw restart attempt source=update target=ai.openclaw.gateway
[2026-05-06T09:38:22Z] openclaw restart done   source=update
[2026-05-06T09:45:09Z] openclaw restart attempt source=update target=ai.openclaw.gateway
[2026-05-06T09:45:10Z] openclaw restart done   source=update

The error is recoverable in user-facing terms — openai-provider-BVG8OXtu.js:225 even prints the right hint:

No API key found for provider "openai". You are authenticated with OpenAI Codex OAuth. Use openai-codex/gpt-5.5, or set OPENAI_API_KEY for direct OpenAI API access.

…but doctor is the thing producing the bad refs in the first place, so simply re-editing the config and restarting works only until the next doctor run.

Suspected location

dist/doctor-config-flow-D_wwaDIB.js:141:

const LEGACY_MODELS_ADD_CODEX_MODEL_IDS = new Set(["gpt-5.5", "gpt-5.5-pro"]);
function isLegacyModelsAddCodexMetadataModel(params) {
  // returns true for openai-codex/gpt-5.5 with the canonical reasoning/image/cost shape
}

The _ADD_CODEX_ naming suggests this branch is meant to add the -codex prefix, but the observed effect is the opposite (strip it). Either the call-site that consumes this set is inverted, or there is a sibling _REMOVE_CODEX_ migration acting on these model ids. The exact mutator is not in doctor-config-flow-D_wwaDIB.js directly; it is invoked from the broader doctor flow during --fix.

Workaround

  1. cp ~/.openclaw/openclaw.json.bak.1 ~/.openclaw/openclaw.json (the pre-doctor backup), or
  2. Manually re-prefix every openai/gpt-5.X* back to openai-codex/gpt-5.X* in modelOverride.{primary,fallbacks} and modelCatalog.
  3. Avoid running openclaw doctor --fix until this is patched.

Happy to attach the full pre/post openclaw.json diff or the redacted config-audit excerpt if useful.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix [Bug]: openclaw doctor --fix rewrites openai-codex/* model refs to openai/* on 2026.5.4 → 2026.5.5 update, locking out ChatGPT-OAuth users [4 pull requests, 15 comments, 10 participants]