openclaw - 💡(How to fix) Fix [Bug]: `openclaw doctor` (without `--fix`) emits `◇ Doctor changes: Removed agents.defaults.agentRuntime` in past tense even when nothing was changed — reproduces on `v2026.5.10-beta.1` [1 pull requests]

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…

Running openclaw doctor (no --fix) on v2026.5.10-beta.1 (today's latest beta on npm) against a config that still carries the legacy agents.defaults.agentRuntime key prints three contradictory panels in one run: a ◇ Legacy config keys detected panel saying the key is still ignored and the user must run --fix, a ◇ Doctor changes panel saying "Removed agents.defaults.agentRuntime; runtime is now provider/model scoped." (past tense, as if migration already happened), and a final ◇ Doctor panel hinting again to run --fix to migrate. After the read-only doctor run, the config file on disk still contains agents.defaults.agentRuntime, so the past-tense "Removed" claim is false.

Root Cause

The same pattern is in play at every other "Doctor changes" emit site in the file (:124, :143, :155, :202, :268) and across the doctor flow (src/flows/doctor-health-contributions.ts:247, src/commands/doctor-auth-flat-profiles.ts:265, src/commands/doctor-state-integrity.ts:1035, src/commands/doctor-skills.ts:109, src/commands/doctor-config-preflight.ts:97, :107, src/commands/doctor-memory-search.ts:267, :297, src/commands/doctor-cron.ts:261, :265, src/commands/doctor-sandbox.ts:271, :320, src/commands/doctor-plugin-manifests.ts:207, src/commands/doctor-workspace.ts:295, src/commands/doctor/emit-notes.ts:16). Any of them can fire past-tense without --fix. This bug is more visible for the agents.defaults.agentRuntime migration because the matching legacy-keys panel screams loudly about the same key being still-broken in the very same run, making the contradiction obvious.

Fix Action

Fixed

Code Example

"agents": {
     "defaults": {
       "agentRuntime": { "id": "claude-cli" }
     }
   }

---

pnpm openclaw doctor

---

$ pnpm openclaw config get agents.defaults.agentRuntime
   { "id": "claude-cli" }   # still there, despite the "Removed" panel

---

Legacy config keys detected ───────────────────────────────────────╮
│                                                                     │
- agents.defaults.agentRuntime: agents.defaults.agentRuntime is    │
│    ignored; set models.providers.<provider>.agentRuntime or a       │
│    model-scoped agentRuntime instead. Run "openclaw doctor --fix".  
│                                                                     │
├─────────────────────────────────────────────────────────────────────╯

Doctor changes ──────────────────────────────────────────────────────╮
│                                                                       │
Removed agents.defaults.agentRuntime; runtime is now provider/model  │
│  scoped.                                                              
│                                                                       │
├───────────────────────────────────────────────────────────────────────╯

Doctor warnings ──────────────────────────────────────────────────────╮
│                                                                        │
- channels.slack.groupPolicy is "allowlist" but groupAllowFrom (and   │
│    allowFrom) is empty — all group messages will be silently dropped.  
│  …                                                                     │
│                                                                        │
├────────────────────────────────────────────────────────────────────────╯

Doctor ─────────────────────────────────────────────────────╮
│                                                              │
Run "openclaw doctor --fix" to migrate legacy config keys.  
│                                                              │
├──────────────────────────────────────────────────────────────╯

---

$ pnpm openclaw config get agents.defaults.agentRuntime
{
  "id": "claude-cli"
}

---

if (legacyStep.changeLines.length > 0) {
    note(legacyStep.changeLines.join("\n"), "Doctor changes");
  }

---

return {
    cfg: params.shouldRepair ? params.mutation.config : params.state.cfg,
  };

---
RAW_BUFFERClick to expand / collapse

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

Running openclaw doctor (no --fix) on v2026.5.10-beta.1 (today's latest beta on npm) against a config that still carries the legacy agents.defaults.agentRuntime key prints three contradictory panels in one run: a ◇ Legacy config keys detected panel saying the key is still ignored and the user must run --fix, a ◇ Doctor changes panel saying "Removed agents.defaults.agentRuntime; runtime is now provider/model scoped." (past tense, as if migration already happened), and a final ◇ Doctor panel hinting again to run --fix to migrate. After the read-only doctor run, the config file on disk still contains agents.defaults.agentRuntime, so the past-tense "Removed" claim is false.

Steps to reproduce

  1. On v2026.5.10-beta.1 (commit 9c7e67b0f8), with a config that has the legacy key set:

    "agents": {
      "defaults": {
        "agentRuntime": { "id": "claude-cli" }
      }
    }

    This shape is the normal carryover from any pre-5.10-beta install — it is exactly what the legacy-keys detector is built to catch.

  2. Run openclaw doctor without --fix:

    pnpm openclaw doctor
  3. Observe the three contradictory panels described below.

  4. Confirm the disk config is unchanged:

    $ pnpm openclaw config get agents.defaults.agentRuntime
    { "id": "claude-cli" }   # still there, despite the "Removed" panel

Expected behavior

When doctor is run without --fix, the proposed mutations should be rendered in future tense (or in a panel titled to signal that nothing was applied), e.g. one of:

  • ◇ Pending migrations (run --fix to apply): Would remove agents.defaults.agentRuntime; runtime is now provider/model scoped.
  • A different panel title, e.g. ◇ Doctor preview instead of ◇ Doctor changes.
  • Or simply suppress the panel when shouldRepair === false and rely on the existing Legacy config keys detected + final hint to drive the user to --fix.

The current past-tense Removed claim should only render when the change was actually applied.

Actual behavior

Verbatim doctor output on v2026.5.10-beta.1 (commit 9c7e67b0f8), invocation pnpm openclaw doctor:

◇  Legacy config keys detected ───────────────────────────────────────╮
│                                                                     │
│  - agents.defaults.agentRuntime: agents.defaults.agentRuntime is    │
│    ignored; set models.providers.<provider>.agentRuntime or a       │
│    model-scoped agentRuntime instead. Run "openclaw doctor --fix".  │
│                                                                     │
├─────────────────────────────────────────────────────────────────────╯

◇  Doctor changes ──────────────────────────────────────────────────────╮
│                                                                       │
│  Removed agents.defaults.agentRuntime; runtime is now provider/model  │
│  scoped.                                                              │
│                                                                       │
├───────────────────────────────────────────────────────────────────────╯

◇  Doctor warnings ──────────────────────────────────────────────────────╮
│                                                                        │
│  - channels.slack.groupPolicy is "allowlist" but groupAllowFrom (and   │
│    allowFrom) is empty — all group messages will be silently dropped.  │
│  …                                                                     │
│                                                                        │
├────────────────────────────────────────────────────────────────────────╯

◇  Doctor ─────────────────────────────────────────────────────╮
│                                                              │
│  Run "openclaw doctor --fix" to migrate legacy config keys.  │
│                                                              │
├──────────────────────────────────────────────────────────────╯

Post-run config check (proves nothing was actually removed):

$ pnpm openclaw config get agents.defaults.agentRuntime
{
  "id": "claude-cli"
}

So in one doctor run:

  1. Panel 1 (Legacy config keys detected) says the key is still ignored and needs --fix to be migrated. Accurate — the key is still there.
  2. Panel 2 (Doctor changes) says "Removed agents.defaults.agentRuntime"past tense, implies the migration happened. Inaccurate — nothing was written to disk.
  3. Panel 4 (final Doctor hint) says "Run "openclaw doctor --fix" to migrate legacy config keys." — implies the migration has NOT happened yet. Accurate.

Panels 1 and 4 imply the migration is pending; Panel 2 implies it already happened. A user reading top-to-bottom cannot tell which is true without checking the config file by hand.

Tracing in source on v2026.5.10-beta.1:

  • src/commands/doctor-config-flow.ts:123-125:

    if (legacyStep.changeLines.length > 0) {
      note(legacyStep.changeLines.join("\n"), "Doctor changes");
    }

    The panel fires whenever legacyStep.changeLines is non-empty — there is no gate on shouldRepair.

  • The legacyStep object updates in-memory candidate / pendingChanges at src/commands/doctor-config-flow.ts:89, but the actual write to disk is gated downstream on shouldRepair via applyDoctorConfigMutation (src/commands/doctor/shared/config-mutation-state.ts:15-34):

    return {
      cfg: params.shouldRepair ? params.mutation.config : params.state.cfg,
    };

So the past-tense rendering precedes the conditional apply — and when --fix is not passed, the rendering is decoupled from reality.

The same pattern is in play at every other "Doctor changes" emit site in the file (:124, :143, :155, :202, :268) and across the doctor flow (src/flows/doctor-health-contributions.ts:247, src/commands/doctor-auth-flat-profiles.ts:265, src/commands/doctor-state-integrity.ts:1035, src/commands/doctor-skills.ts:109, src/commands/doctor-config-preflight.ts:97, :107, src/commands/doctor-memory-search.ts:267, :297, src/commands/doctor-cron.ts:261, :265, src/commands/doctor-sandbox.ts:271, :320, src/commands/doctor-plugin-manifests.ts:207, src/commands/doctor-workspace.ts:295, src/commands/doctor/emit-notes.ts:16). Any of them can fire past-tense without --fix. This bug is more visible for the agents.defaults.agentRuntime migration because the matching legacy-keys panel screams loudly about the same key being still-broken in the very same run, making the contradiction obvious.

OpenClaw version

v2026.5.10-beta.1

Operating system

Ubuntu 24.04

Install method

No response

Model

Not applicable

Provider / routing chain

Not applicable

Additional provider/model setup details

No response

Logs, screenshots, and evidence

Impact and severity

No response

Additional information

No response

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…

FAQ

Expected behavior

When doctor is run without --fix, the proposed mutations should be rendered in future tense (or in a panel titled to signal that nothing was applied), e.g. one of:

  • ◇ Pending migrations (run --fix to apply): Would remove agents.defaults.agentRuntime; runtime is now provider/model scoped.
  • A different panel title, e.g. ◇ Doctor preview instead of ◇ Doctor changes.
  • Or simply suppress the panel when shouldRepair === false and rely on the existing Legacy config keys detected + final hint to drive the user to --fix.

The current past-tense Removed claim should only render when the change was actually applied.

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 - 💡(How to fix) Fix [Bug]: `openclaw doctor` (without `--fix`) emits `◇ Doctor changes: Removed agents.defaults.agentRuntime` in past tense even when nothing was changed — reproduces on `v2026.5.10-beta.1` [1 pull requests]