Skip to content

Commit 0ee52e9

Browse files
committed
fix: keep config recovery in doctor
1 parent dc32acd commit 0ee52e9

23 files changed

Lines changed: 255 additions & 1078 deletions

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Docs: https://docs.openclaw.ai
1212

1313
- Agents/tools: skip optional media and PDF tool factories when the effective tool denylist already blocks them, avoiding unnecessary hot-path setup for tools that will be filtered out before model use. (#76773) Thanks @dorukardahan.
1414
- Discord/status: let explicit reaction tool calls opt into tracking subsequent tool progress on the reacted message with `trackToolCalls: true`, and use the shared tool display emoji table for status reactions.
15+
- Gateway/config: stop Gateway startup and hot reload from auto-restoring invalid config; invalid config now fails closed and `openclaw doctor --fix` owns last-known-good repair.
1516
- Gateway/performance: lazy-load early runtime discovery and shutdown-hook helpers, defer maintenance timers until after readiness, and trim duplicate plugin auto-enable work during Gateway startup.
1617
- QA/Mantis: add a `pnpm openclaw qa mantis discord-smoke` runner and manual GitHub workflow that verify the Mantis Discord bot can see the configured guild/channel, post a smoke message, add a reaction, and upload artifacts.
1718
- Gateway/performance: lazy-load the heavy cron runtime after the rest of Gateway startup, defer restart-sentinel refresh after readiness, and let the Gateway startup benchmark write per-run V8 CPU profiles with `--cpu-prof-dir`.

docs/cli/config.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -439,9 +439,9 @@ ls -lt "$CONFIG".rejected.* 2>/dev/null | head
439439
openclaw config validate
440440
```
441441

442-
Direct editor writes are still allowed, but the running Gateway treats them as untrusted until they validate. Invalid direct edits can be restored from the last-known-good backup during startup or hot reload. See [Gateway troubleshooting](/gateway/troubleshooting#gateway-restored-last-known-good-config).
442+
Direct editor writes are still allowed, but the running Gateway treats them as untrusted until they validate. Invalid direct edits fail startup or are skipped by hot reload; Gateway does not rewrite `openclaw.json`. Run `openclaw doctor --fix` to repair prefixed/clobbered config or restore the last-known-good copy. See [Gateway troubleshooting](/gateway/troubleshooting#gateway-rejected-invalid-config).
443443

444-
Whole-file recovery is reserved for globally broken config, such as parse errors, root-level schema failures, legacy migration failures, or mixed plugin and root failures. If validation fails only under `plugins.entries.<id>...`, OpenClaw keeps the active `openclaw.json` in place and reports the plugin-local issue instead of restoring `.last-good`. This prevents plugin schema changes or `minHostVersion` skew from rolling back unrelated user settings such as models, providers, auth profiles, channels, gateway exposure, tools, memory, browser, or cron config.
444+
Whole-file recovery is reserved for doctor repair. Plugin schema changes or `minHostVersion` skew stay loud instead of rolling back unrelated user settings such as models, providers, auth profiles, channels, gateway exposure, tools, memory, browser, or cron config.
445445

446446
## Subcommands
447447

docs/cli/plugins.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,10 @@ is available, then fall back to `latest`.
104104
</Note>
105105

106106
<AccordionGroup>
107-
<Accordion title="Config includes and invalid-config recovery">
107+
<Accordion title="Config includes and invalid-config repair">
108108
If your `plugins` section is backed by a single-file `$include`, `plugins install/update/enable/disable/uninstall` write through to that included file and leave `openclaw.json` untouched. Root includes, include arrays, and includes with sibling overrides fail closed instead of flattening. See [Config includes](/gateway/configuration) for the supported shapes.
109109

110-
If config is invalid during install, `plugins install` normally fails closed and tells you to run `openclaw doctor --fix` first. During Gateway startup, invalid config for one plugin is isolated to that plugin so other channels and plugins can keep running; `openclaw doctor --fix` can quarantine the invalid plugin entry. The only documented install-time exception is a narrow bundled-plugin recovery path for plugins that explicitly opt into `openclaw.install.allowInvalidConfigRecovery`.
110+
If config is invalid during install, `plugins install` normally fails closed and tells you to run `openclaw doctor --fix` first. During Gateway startup and hot reload, invalid plugin config fails closed like any other invalid config; `openclaw doctor --fix` can quarantine the invalid plugin entry. The only documented install-time exception is a narrow bundled-plugin recovery path for plugins that explicitly opt into `openclaw.install.allowInvalidConfigRecovery`.
111111

112112
</Accordion>
113113
<Accordion title="--force and reinstall vs update">

docs/gateway/configuration.md

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -89,17 +89,13 @@ When validation fails:
8989
- Run `openclaw doctor` to see exact issues
9090
- Run `openclaw doctor --fix` (or `--yes`) to apply repairs
9191

92-
The Gateway keeps a trusted last-known-good copy after each successful startup.
93-
If `openclaw.json` later fails validation (or drops `gateway.mode`, shrinks
94-
sharply, or has a stray log line prepended), OpenClaw preserves the broken file
95-
as `.clobbered.*`, restores the last-known-good copy, and logs the recovery
96-
reason. The next agent turn also receives a system-event warning so the main
97-
agent does not blindly rewrite the restored config. Promotion to last-known-good
98-
is skipped when a candidate contains redacted secret placeholders such as `***`.
99-
When every validation issue is scoped to `plugins.entries.<id>...`, OpenClaw
100-
does not perform whole-file recovery. It keeps the current config active and
101-
surfaces the plugin-local failure so a plugin schema or host-version mismatch
102-
cannot roll back unrelated user settings.
92+
The Gateway keeps a trusted last-known-good copy after each successful startup,
93+
but startup and hot reload do not restore it automatically. If `openclaw.json`
94+
fails validation (including plugin-local validation), Gateway startup fails or
95+
the reload is skipped and the current runtime keeps the last accepted config.
96+
Run `openclaw doctor --fix` (or `--yes`) to repair prefixed/clobbered config or
97+
restore the last-known-good copy. Promotion to last-known-good is skipped when a
98+
candidate contains redacted secret placeholders such as `***`.
10399

104100
## Common tasks
105101

@@ -539,20 +535,15 @@ The Gateway watches `~/.openclaw/openclaw.json` and applies changes automaticall
539535

540536
Direct file edits are treated as untrusted until they validate. The watcher waits
541537
for editor temp-write/rename churn to settle, reads the final file, and rejects
542-
invalid external edits by restoring the last-known-good config. OpenClaw-owned
543-
config writes use the same schema gate before writing; destructive clobbers such
544-
as dropping `gateway.mode` or shrinking the file by more than half are rejected
545-
and saved as `.rejected.*` for inspection.
546-
547-
Plugin-local validation failures are the exception: if all issues are under
548-
`plugins.entries.<id>...`, reload keeps the current config and reports the plugin
549-
issue instead of restoring `.last-good`.
550-
551-
If you see `Config auto-restored from last-known-good` or
552-
`config reload restored last-known-good config` in logs, inspect the matching
553-
`.clobbered.*` file next to `openclaw.json`, fix the rejected payload, then run
554-
`openclaw config validate`. See [Gateway troubleshooting](/gateway/troubleshooting#gateway-restored-last-known-good-config)
555-
for the recovery checklist.
538+
invalid external edits without rewriting `openclaw.json`. OpenClaw-owned config
539+
writes use the same schema gate before writing; destructive clobbers such as
540+
dropping `gateway.mode` or shrinking the file by more than half are rejected and
541+
saved as `.rejected.*` for inspection.
542+
543+
If you see `config reload skipped (invalid config)` or startup reports `Invalid
544+
config`, inspect the config, run `openclaw config validate`, then run `openclaw
545+
doctor --fix` for repair. See [Gateway troubleshooting](/gateway/troubleshooting#gateway-rejected-invalid-config)
546+
for the checklist.
556547

557548
### Reload modes
558549

docs/gateway/troubleshooting.md

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -300,9 +300,10 @@ Related:
300300
- [Configuration](/gateway/configuration)
301301
- [Doctor](/gateway/doctor)
302302

303-
## Gateway restored last-known-good config
303+
## Gateway rejected invalid config
304304

305-
Use this when the Gateway starts, but logs say it restored `openclaw.json`.
305+
Use this when Gateway startup fails with `Invalid config` or hot reload logs say
306+
it skipped an invalid edit.
306307

307308
```bash
308309
openclaw logs --follow
@@ -313,19 +314,19 @@ openclaw doctor
313314

314315
Look for:
315316

316-
- `Config auto-restored from last-known-good`
317-
- `gateway: invalid config was restored from last-known-good backup`
318-
- `config reload restored last-known-good config after invalid-config`
319-
- A timestamped `openclaw.json.clobbered.*` file beside the active config
320-
- A main-agent system event that starts with `Config recovery warning`
317+
- `Invalid config at ...`
318+
- `config reload skipped (invalid config): ...`
319+
- `Config write rejected: ...`
320+
- A timestamped `openclaw.json.rejected.*` file beside the active config
321+
- A timestamped `openclaw.json.clobbered.*` file if `doctor --fix` repaired a broken direct edit
321322

322323
<AccordionGroup>
323324
<Accordion title="What happened">
324-
- The rejected config did not validate during startup or hot reload.
325-
- OpenClaw preserved the rejected payload as `.clobbered.*`.
326-
- The active config was restored from the last validated last-known-good copy.
327-
- The next main-agent turn is warned not to blindly rewrite the rejected config.
328-
- If all validation issues were under `plugins.entries.<id>...`, OpenClaw would not restore the whole file. Plugin-local failures stay loud while unrelated user settings remain in the active config.
325+
- The config did not validate during startup, hot reload, or an OpenClaw-owned write.
326+
- Gateway startup fails closed instead of rewriting `openclaw.json`.
327+
- Hot reload skips invalid external edits and keeps the current runtime config active.
328+
- OpenClaw-owned writes reject invalid/destructive payloads before commit and save `.rejected.*`.
329+
- `openclaw doctor --fix` owns repair. It can remove non-JSON prefixes or restore the last-known-good copy while preserving the rejected payload as `.clobbered.*`.
329330

330331
</Accordion>
331332
<Accordion title="Inspect and repair">
@@ -338,16 +339,17 @@ Look for:
338339
```
339340
</Accordion>
340341
<Accordion title="Common signatures">
341-
- `.clobbered.*` exists → an external direct edit or startup read was restored.
342+
- `.clobbered.*` exists → doctor preserved a broken external edit while repairing the active config.
342343
- `.rejected.*` exists → an OpenClaw-owned config write failed schema or clobber checks before commit.
343344
- `Config write rejected:` → the write tried to drop required shape, shrink the file sharply, or persist invalid config.
344-
- `Rejected validation details:` → the recovery log or main-agent notice includes the schema path that caused the restore, such as `agents.defaults.execution` or `gateway.auth.password.source`.
345-
- `missing-meta-vs-last-good`, `gateway-mode-missing-vs-last-good`, or `size-drop-vs-last-good:*` → startup treated the current file as clobbered because it lost fields or size compared with the last-known-good backup.
345+
- `config reload skipped (invalid config):` → a direct edit failed validation and was ignored by the running Gateway.
346+
- `Invalid config at ...` → startup failed before Gateway services booted.
347+
- `missing-meta-vs-last-good`, `gateway-mode-missing-vs-last-good`, or `size-drop-vs-last-good:*` → an OpenClaw-owned write was rejected because it lost fields or size compared with the last-known-good backup.
346348
- `Config last-known-good promotion skipped` → the candidate contained redacted secret placeholders such as `***`.
347349

348350
</Accordion>
349351
<Accordion title="Fix options">
350-
1. Keep the restored active config if it is correct.
352+
1. Run `openclaw doctor --fix` to let doctor repair prefixed/clobbered config or restore last-known-good.
351353
2. Copy only the intended keys from `.clobbered.*` or `.rejected.*`, then apply them with `openclaw config set` or `config.patch`.
352354
3. Run `openclaw config validate` before restarting.
353355
4. If you edit by hand, keep the full JSON5 config, not just the partial object you wanted to change.

docs/help/faq.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -804,15 +804,15 @@ lives on the [First-run FAQ](/help/faq-first-run).
804804

805805
- OpenClaw-owned config writes validate the full post-change config before writing.
806806
- Invalid or destructive OpenClaw-owned writes are rejected and saved as `openclaw.json.rejected.*`.
807-
- If a direct edit breaks startup or hot reload, the Gateway restores the last-known-good config and saves the rejected file as `openclaw.json.clobbered.*`.
808-
- The main agent receives a boot warning after recovery so it does not blindly write the bad config again.
807+
- If a direct edit breaks startup or hot reload, Gateway fails closed or skips the reload; it does not rewrite `openclaw.json`.
808+
- `openclaw doctor --fix` owns repair and can restore last-known-good while saving the rejected file as `openclaw.json.clobbered.*`.
809809

810810
Recover:
811811

812-
- Check `openclaw logs --follow` for `Config auto-restored from last-known-good`, `Config write rejected:`, or `config reload restored last-known-good config`.
812+
- Check `openclaw logs --follow` for `Invalid config at`, `Config write rejected:`, or `config reload skipped (invalid config)`.
813813
- Inspect the newest `openclaw.json.clobbered.*` or `openclaw.json.rejected.*` beside the active config.
814-
- Keep the active restored config if it works, then copy only the intended keys back with `openclaw config set` or `config.patch`.
815-
- Run `openclaw config validate` and `openclaw doctor`.
814+
- Run `openclaw config validate` and `openclaw doctor --fix`.
815+
- Copy only the intended keys back with `openclaw config set` or `config.patch`.
816816
- If you have no last-known-good or rejected payload, restore from backup, or re-run `openclaw doctor` and reconfigure channels/models.
817817
- If this was unexpected, file a bug and include your last known config or any backup.
818818
- A local coding agent can often reconstruct a working config from logs or history.
@@ -825,7 +825,7 @@ lives on the [First-run FAQ](/help/faq-first-run).
825825
- Use `config.patch` for partial RPC edits; keep `config.apply` for full-config replacement only.
826826
- If you are using the owner-only `gateway` tool from an agent run, it will still reject writes to `tools.exec.ask` / `tools.exec.security` (including legacy `tools.bash.*` aliases that normalize to the same protected exec paths).
827827

828-
Docs: [Config](/cli/config), [Configure](/cli/configure), [Gateway troubleshooting](/gateway/troubleshooting#gateway-restored-last-known-good-config), [Doctor](/gateway/doctor).
828+
Docs: [Config](/cli/config), [Configure](/cli/configure), [Gateway troubleshooting](/gateway/troubleshooting#gateway-rejected-invalid-config), [Doctor](/gateway/doctor).
829829

830830
</Accordion>
831831

docs/tools/plugin.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,10 @@ If config is invalid, install normally fails closed and points you at
9999
`openclaw doctor --fix`. The only recovery exception is a narrow bundled-plugin
100100
reinstall path for plugins that opt into
101101
`openclaw.install.allowInvalidConfigRecovery`.
102-
During Gateway startup, invalid config for one plugin is isolated to that plugin:
103-
startup logs the `plugins.entries.<id>.config` issue, skips that plugin during
104-
load, and keeps other plugins and channels online. Run `openclaw doctor --fix`
105-
to quarantine the bad plugin config by disabling that plugin entry and removing
106-
its invalid config payload; the normal config backup keeps the previous values.
102+
During Gateway startup, invalid plugin config fails closed like any other invalid
103+
config. Run `openclaw doctor --fix` to quarantine the bad plugin config by
104+
disabling that plugin entry and removing its invalid config payload; the normal
105+
config backup keeps the previous values.
107106
When a channel config references a plugin that is no longer discoverable but the
108107
same stale plugin id remains in plugin config or install records, Gateway startup
109108
logs warnings and skips that channel instead of blocking every other channel.

0 commit comments

Comments
 (0)