Skip to content

[Bug] v2026.6.11 published dist missing reentrancy guard - reply session initialization conflicted #98416

Description

@yaaboo-gif

Summary

v2026.6.11 source contains commit d2da8c79d9 ("fix(auto-reply): serialize reply session initialization"), which adds reentrant: true to commitReplySessionInitialization's updateSessionStore call AND the matching AsyncLocalStorage reentrancy support in src/shared/store-writer-queue.ts.

However, the published npm v2026.6.11 bundle ships the dist for session-accessor with the reentrant: true call, but ships store-writer-queue as a 72-line pre-fix module without any AsyncLocalStorage / isActiveStoreWriter / runActiveStoreWriter implementation.

This means at runtime the reentrant: true option passed by commitReplySessionInitialization is silently dropped by runExclusiveSessionStoreWrite (which doesn't even accept an opts argument in the dist), and the reentrancy guard never activates. The fix in d2da8c79d9 is therefore not effective in the published v2026.6.11 artifact, even though it is "in the release" by source-tree presence.

Environment

  • OpenClaw version: 2026.6.11 (npm global install)
  • Source tag for 6.11: 66e676d29b (2026-06-30 10:49 -0700)
  • Fix commit: d2da8c79d9 (Ayaan Zaidi, 2026-06-25 12:11 -0700) — included in 6.11 by ancestry
  • OS: Ubuntu 24.04, Linux x64, Node v24.18.0
  • Channel: webchat (agent:main:main)
  • Trigger: short-turn webchat conversation, no thinking mode, model replies in <1s

Observed behavior

Webchat agent:main:main sessions fail with:

[diagnostic] message dispatch completed: channel=webchat sessionId=unknown sessionKey=agent:main:main source=replyResolver outcome=error duration=12ms error="Error: reply session initialization conflicted for agent:main:main"
[diagnostic] message processed: ... outcome=error ... error="Error: reply session initialization conflicted for agent:main:main"

The error appears after 1–2 short turns and remains until the gateway is restarted. The session is unusable afterwards; /reset hits the same error.

Reproduction frequency in our install: ~13 errors in a single minute at the peak:

$ journalctl --user -u openclaw-gateway --since "2026-07-01 11:55" --no-pager | grep -c "reply session initialization conflicted"
13

Root cause analysis

Step 1: source vs dist divergence

The 6.11 source src/shared/store-writer-queue.ts (tag 66e676d29b) contains 4 occurrences of AsyncLocalStorage / isActiveStoreWriter, added by d2da8c79d9:

$ git show 66e676d29b:src/shared/store-writer-queue.ts | grep -c "AsyncLocalStorage\|isActiveStoreWriter"
4

The pre-fix 6.10 source has 0:

$ git show d2da8c79d9~1:src/shared/store-writer-queue.ts | grep -c "AsyncLocalStorage\|isActiveStoreWriter"
0

Step 2: dist file inspection

The published npm package contains:

/root/.nvm/versions/node/v24.18.0/lib/node_modules/openclaw/dist/store-writer-queue-Cs_NM_XG.js

which is 72 lines and contains the OLD queue logic with no AsyncLocalStorage, no isActiveStoreWriter, no runActiveStoreWriter. The runQueuedStoreWrite signature in the dist is the pre-fix form:

async function runQueuedStoreWrite(params) {
 if (!params.storePath || typeof params.storePath !== "string") throw new Error(...);
 const queue = getOrCreateStoreWriterQueue(params.queues, params.storePath);
 return await new Promise((resolve, reject) => {
 const task = { fn: async () => await params.fn(), resolve, reject };
 queue.pending.push(task);
 drainStoreWriterQueue(params.queues, params.storePath);
 });
}

There is no params.reentrant handling.

The runExclusiveSessionStoreWrite wrapper in the dist is also the pre-fix two-arg form:

async function runExclusiveSessionStoreWrite(storePath, fn) {
 return await runQueuedStoreWrite({
 queues: WRITER_QUEUES,
 storePath,
 label: "runExclusiveSessionStoreWrite",
 fn
 });
}

So the dist does not even forward an opts argument to the queue.

Step 3: the only reentrant: true site in the dist

The dist file session-accessor-DvSc996e.js does contain a reentrant: true line at the expected call site inside commitReplySessionInitialization:

$ grep -n "reentrant" session-accessor-DvSc996e.js
1848: reentrant: true,

But this option is passed as the third argument of updateSessionStore, and the dist updateSessionStore signature is:

async function updateSessionStore(storePath, mutator, opts) {
 return await runExclusiveSessionStoreWrite(storePath, async () => { ... });
}

i.e. opts is not forwarded to runExclusiveSessionStoreWrite, which in turn does not accept an opts argument. The reentrant: true is therefore silently dropped on the floor.

Step 4: confirmation

$ grep -rn "params\.reentrant\|opts\.reentrant\|\.reentrant" *.js | grep -i "store-writer"
(no matches)

The reentrant field is read in exactly zero places in the dist.

Expected behavior

The fix in d2da8c79d9 should be effective in the published v2026.6.11 artifact: a transient reply-session initialization stale-snapshot conflict should not block the user-facing message, and commitReplySessionInitialization should be able to call updateSessionStore reentrantly from inside the initSessionStateAttempt writer queue without dropping the reentrant: true hint.

Actual behavior

In the published v2026.6.11 dist:

  • commitReplySessionInitialization passes reentrant: true to updateSessionStore
  • updateSessionStore discards it
  • The reentrancy guard is never installed
  • stale-snapshot is returned from commitReplySessionInitialization on benign concurrent session-row churn (delivery timestamps, token/session status, restart recovery, active-memory/compaction metadata — see Signal direct inbound can be dropped on reply session initialization conflict in 2026.6.11 release #98234 for a detailed list)
  • The guarded reply-session initialization throws reply session initialization conflicted for <sessionKey>, and the inbound message is dropped

Impact

High for any user on 6.11 who is not on the main branch — i.e. every npm install of 6.11. Webchat / Signal / Telegram / WhatsApp / DM-bound channels are all affected to the extent they use commitReplySessionInitialization. From the GitHub issue tracker, reports of this exact symptom on 6.11 (not beta) include:

So far, at least 7 GitHub issues report this exact error string. The bundling divergence is, in our view, a release blocker for 6.11.

Suggested fix paths (for maintainers)

Any of the following would restore parity with the source:

  1. Re-bundle src/shared/store-writer-queue.ts for the next npm release, including the AsyncLocalStorage / isActiveStoreWriter / runActiveStoreWriter block from d2da8c79d9 (~+43 lines), and add the opts parameter to runExclusiveSessionStoreWrite in src/config/sessions/store-writer.ts.
  2. Add a release-bundle smoke test that asserts the dist store-writer-queue module exports a reentrant-aware runQueuedStoreWrite whenever the source has it; this would have caught the divergence.
  3. Backport the 75db48a175 follow-up (compare reply init revisions using persisted shape, PR fix: prevent stale skill snapshots blocking Discord replies #97657) alongside the re-bundle to also reduce false-conflict frequency from runtime-only field churn.

Local mitigation (not a real fix)

We have locally tried two mitigations; both are workarounds only:

  • Hot-patch the dist with the missing reentrant plumbing. Requires hand-editing minified code; high regression risk; does not survive npm i -g openclaw@latest.
  • Increase the conflict retry budget in the dist. Found in the wild to make Signal inbound reachable in our install, but again does not survive reinstall and does not address the root cause (transient stale snapshot becomes a hard failure under any concurrent write).

We are happy to assist in a release-blocking patch, validation against the existing src/config/sessions/store-writer.test.ts and src/auto-reply/reply/session.test.ts tests, and a fresh CHANGELOG entry that clearly calls out the 6.11 dist vs source divergence.

Reproduction (very short)

  1. Install [email protected] via npm i -g [email protected].
  2. Start the gateway on a fresh session.
  3. In webchat, take 1–2 short turns (no thinking mode; any model that responds in <1s is sufficient).
  4. Watch journalctl --user -u openclaw-gateway | grep "reply session initialization conflicted".
  5. After 1–2 turns, errors appear. Webchat main becomes unusable until gateway restart.

Evidence checklist

Local environment log (anonymized)

$ cat /root/.config/systemd/user/openclaw-gateway.service | grep Description
Description=OpenClaw Gateway (v2026.6.11)

$ cat /root/.nvm/versions/node/v24.18.0/lib/node_modules/openclaw/package.json | grep version
 "version": "2026.6.11",

$ journalctl --user -u openclaw-gateway --since "2026-07-01 11:55" --no-pager \
 | grep -c "reply session initialization conflicted"
13

Reported by the maintainers of A380 on 6.11 npm install. Same maintainer previously contributed #85704 (memory vector degradation guard) which was merged into main as 16ffc2507.

Metadata

Metadata

Assignees

Labels

P1High-priority user-facing bug, regression, or broken workflow.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.impact:session-stateSession, memory, transcript, context, or agent state can drift or corrupt.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.maturity:stableIssue affects a taxonomy feature currently scored M4/M5.

Type

No type

Fields

Priority

None yet

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions