openclaw - ✅(Solved) Fix Concurrent writes to openclaw.json produce invalid (concatenated) JSON; gateway refuses config until auto-restore [1 pull requests, 1 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#70643Fetched 2026-04-24 05:55:13
View on GitHub
Comments
0
Participants
1
Timeline
1
Reactions
0
Participants
Timeline (top)
cross-referenced ×1

When two OpenClaw processes write to ~/.openclaw/openclaw.json around the same time, the resulting file can contain two concatenated top-level JSON objects rather than a merged one. The gateway then fails to load config, and the UI surfaces this to the user as "agent failed before reply" on the next message. The built-in auto-restore from openclaw.json.last-good recovers correctly, but the failure window can drop at least one user turn.

Root Cause

When two OpenClaw processes write to ~/.openclaw/openclaw.json around the same time, the resulting file can contain two concatenated top-level JSON objects rather than a merged one. The gateway then fails to load config, and the UI surfaces this to the user as "agent failed before reply" on the next message. The built-in auto-restore from openclaw.json.last-good recovers correctly, but the failure window can drop at least one user turn.

Fix Action

Fix / Workaround

That's what doctor wrote (first object) followed by an unmerged agents.defaults.model.primary patch (second object) — the writer appears to have appended instead of merging, producing invalid JSON. The gateway's auto-restore kicked in from openclaw.json.last-good and the system recovered.

PR fix notes

PR #70655: fix(config): serialise concurrent config writes with advisory file lock

Description (problem / solution / changelog)

Summary

Fixes #70643 — Concurrent writes to openclaw.json produce invalid (concatenated) JSON when two processes (e.g. openclaw doctor and the gateway) write simultaneously.

  • Wraps writeConfigFile in the project's existing withFileLock advisory lock mechanism (same pattern used by OAuth store, pairing store, and plugin deduplication)
  • Ensures atomic read-modify-write: only one process writes at a time
  • Re-entrant within a single process (existing HELD_LOCKS map handles recursive writes)
  • Lock options: 20 retries, exponential back-off 50ms–1s, 30s stale window (~10s worst-case wait)

Files changed

  • src/config/io.ts (37 lines added) — import withFileLock, add lock options, wrap write function

Test plan

  • Run openclaw doctor and trigger a model config change simultaneously, verify openclaw.json stays valid
  • Verify the .lock file is created and cleaned up
  • Verify recursive writes (e.g. owner-display-secret auto-persist path) still work

🤖 Generated with Claude Code

Changed files

  • src/config/io.ts (modified, +37/-0)

Code Example

suspicious: ["missing-meta-vs-last-good", "gateway-mode-missing-vs-last-good"]
suspicious: ["reload-invalid-config"]

---

{
  "gateway": { "mode": "local", "auth": {} },
  "wizard":  { "lastRunCommand": "doctor",},
  "meta":    { "lastTouchedAt": "2026-04-23T04:27:20.367Z" }
}
{
  "agents": { "defaults": { "model": { "primary": "claude-cli/claude-opus-4-6" } } }
}
RAW_BUFFERClick to expand / collapse

Summary

When two OpenClaw processes write to ~/.openclaw/openclaw.json around the same time, the resulting file can contain two concatenated top-level JSON objects rather than a merged one. The gateway then fails to load config, and the UI surfaces this to the user as "agent failed before reply" on the next message. The built-in auto-restore from openclaw.json.last-good recovers correctly, but the failure window can drop at least one user turn.

Environment

  • OpenClaw 2026.4.21 (f788c88)
  • Node v22.22.2
  • Linux 6.17.0-22-generic
  • Gateway mode: local

What happened

On 2026-04-23, the config.observe auditor flagged the live config as invalid:

suspicious: ["missing-meta-vs-last-good", "gateway-mode-missing-vs-last-good"]
suspicious: ["reload-invalid-config"]

Both quarantined copies (openclaw.json.clobbered.2026-04-23T04-45-31-{238,252}Z) contain two separate top-level JSON objects, not one:

{
  "gateway": { "mode": "local", "auth": {} },
  "wizard":  { "lastRunCommand": "doctor",},
  "meta":    { "lastTouchedAt": "2026-04-23T04:27:20.367Z" }
}
{
  "agents": { "defaults": { "model": { "primary": "claude-cli/claude-opus-4-6" } } }
}

That's what doctor wrote (first object) followed by an unmerged agents.defaults.model.primary patch (second object) — the writer appears to have appended instead of merging, producing invalid JSON. The gateway's auto-restore kicked in from openclaw.json.last-good and the system recovered.

Suspected cause

Two writers racing without shared locking / atomic read-modify-write. Likely culprits: openclaw doctor and whichever code path sets agents.defaults.model.primary (possibly the gateway itself on startup, or a second CLI invocation). The config-audit log shows the bad reads happened at a gateway PID reading a config produced out-of-band.

Expected

All writers perform atomic merge (read → merge → write-via-tempfile-then-rename) under an advisory lock, so concurrent writes linearize instead of clobbering.

Impact

  • User sees opaque "agent failed before reply" in the web UI until the next gateway reload.
  • Recovery is automatic via last-good, but the current turn is lost.
  • Two openclaw.json.clobbered.* files accumulate per incident (minor).

Repro (suspected, not yet confirmed)

Run a config-touching command (openclaw doctor, openclaw configure, openclaw models auth login …) in parallel with another config-touching command, or while the gateway is writing agents.defaults. The race window is small but likely reproducible under load.

Attachments

Happy to share sanitized copies of the two openclaw.json.clobbered.* files and the relevant config-audit.jsonl lines on request.

extent analysis

TL;DR

Implementing atomic read-modify-write operations with advisory locking can prevent concurrent writes from clobbering the openclaw.json file.

Guidance

  • Investigate the code paths of openclaw doctor and the gateway's startup process to identify where the agents.defaults.model.primary patch is being applied, and ensure that both use atomic merge operations.
  • Implement advisory locking to prevent concurrent writes to openclaw.json.
  • Verify that all writers perform a read-modify-write operation via a temporary file, followed by a rename, to ensure that partial writes do not occur.
  • Review the config-audit.jsonl logs to understand the timing and sequence of events leading up to the clobbering of openclaw.json.

Example

// Pseudocode example of atomic merge operation
function updateConfig(configFile, updates) {
  const tmpFile = `${configFile}.tmp`;
  const configFileContent = readFileSync(configFile);
  const config = JSON.parse(configFileContent);
  // Apply updates to config
  const updatedConfig = { ...config, ...updates };
  writeFileSync(tmpFile, JSON.stringify(updatedConfig));
  renameSync(tmpFile, configFile);
}

Notes

The provided example is a simplified illustration of an atomic merge operation and may require adaptation to the specific requirements of the OpenClaw application.

Recommendation

Apply a workaround by implementing advisory locking and atomic read-modify-write operations to prevent concurrent writes from clobbering the openclaw.json file. This will ensure that the configuration file remains valid and the gateway can load it correctly.

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 Concurrent writes to openclaw.json produce invalid (concatenated) JSON; gateway refuses config until auto-restore [1 pull requests, 1 participants]