Skip to content

fix: sessions.json stale after compaction transcript rotation (deadlock) #88040

@lxiaoy605

Description

@lxiaoy605

Summary

After compaction rotates the transcript to a new session file (truncateAfterCompaction: true), sessions.json still points to the old session file. The old file is in a stale state, and subsequent messages deadlock waiting for a session write lock that never releases.

Root Cause

In src/agents/agent-command.ts (~line 1631), when updating the session store after an agent run:

await updateSessionStoreAfterAgentRun({
  cfg,
  contextTokensOverride: agentCfg?.contextTokens,
  sessionId,   // ← BUG: uses the original sessionId from prepareAgentCommandExecution()
  sessionKey,
  ...
});

sessionId here is resolved at the start of the run via prepareAgentCommandExecution(). But during the run, if automatic compaction triggers and truncateAfterCompaction is enabled, rotateTranscriptAfterCompaction() creates a new session file with a new session ID. The run's internal sessionIdUsed tracks this correctly, and it is written to result.meta.agentMeta.sessionId.

However, updateSessionStoreAfterAgentRun ignores result.meta.agentMeta.sessionId and uses the caller's sessionId parameter. Since the caller passes the original (pre-rotation) ID, sessions.json is never updated to reflect the new session file.

Reproduction

  1. Set compaction.truncateAfterCompaction: true
  2. Have a session that triggers automatic compaction (token budget exceeded)
  3. After compaction rotates the transcript, send another message
  4. Observe: sessions.json points to old session file → new run tries to acquire lock on old file → timeout → deadlock

Fix

One-line fix in src/agents/agent-command.ts:

- sessionId,
+ sessionId: result?.meta?.agentMeta?.sessionId ?? sessionId,

Impact

Any session with truncateAfterCompaction: true that triggers automatic compaction during a run. The /compact command path is unaffected (it uses incrementCompactionCount which handles newSessionId correctly).

Version

2026.5.22

Metadata

Metadata

Assignees

Labels

P2Normal backlog priority with limited blast radius.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.clawsweeper:queueable-fixClawSweeper marked this issue as an existing queue_fix_pr work candidate.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:crash-loopCrash, hang, restart loop, or process-level availability failure.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.

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions