claude-code - 💡(How to fix) Fix Session JSONL corruption from non-atomic writes during concurrent tool execution [1 comments, 2 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
anthropics/claude-code#45286Fetched 2026-04-09 08:08:54
View on GitHub
Comments
1
Participants
2
Timeline
5
Reactions
0
Author
Timeline (top)
labeled ×4commented ×1

Error Message

Claude Code sessions become permanently unresumable with API Error: 400 due to tool use concurrency issues when the JSONL session file is partially written during concurrent tool execution.

Root Cause

Root Cause (Inference)

Fix Action

Workaround

Manually repair the JSONL by:

  1. Finding the orphaned tool_result (parent UUID points to missing entry)
  2. Injecting a synthetic tool_result for the orphaned tool_use
  3. Resuming the session

This is fragile and requires understanding the JSONL format.

Code Example

1. Write session data to a temporary file (same directory)
2. fsync the temporary file
3. Rename temporary file to the session file (atomic on POSIX)
RAW_BUFFERClick to expand / collapse

Bug Description

Claude Code sessions become permanently unresumable with API Error: 400 due to tool use concurrency issues when the JSONL session file is partially written during concurrent tool execution.

Steps to Reproduce

  1. Start a session with multiple concurrent tool calls (3+ parallel MCP tool calls or subagent dispatches)
  2. While tools are executing, trigger a state change (enter plan mode via Shift+Tab, or send a new message)
  3. The session hits 400 and cannot continue. /rewind sometimes helps but often the corruption persists.

Root Cause (Inference)

The session file appears to be written non-atomically. When multiple tool results are being written concurrently, one entry can be dropped — leaving a tool_use in the assistant message with no matching tool_result in the user message. Every subsequent API call fails validation.

Evidence from affected sessions:

  • Assistant message contains 3 tool_use blocks
  • Following user message contains only 2 tool_result blocks
  • The missing tool_result was never written to the JSONL
  • The orphaned tool_use ID has no matching result anywhere in the file

Environment

  • Claude Code CLI: 2.1.85 (also reproduced on 2.1.89-2.1.91)
  • macOS 15.x (Darwin 25.4.0)
  • Reproduction rate: approximately 1 in 10 sessions with heavy tool use
  • Higher rate when using MCP tools (external services, database connectors)

Suggested Fix

Use atomic write pattern for session persistence:

1. Write session data to a temporary file (same directory)
2. fsync the temporary file
3. Rename temporary file to the session file (atomic on POSIX)

This is a standard pattern for crash-safe file updates. The current approach of writing directly to the session file creates a window where interruption leaves the file in an inconsistent state.

Workaround

Manually repair the JSONL by:

  1. Finding the orphaned tool_result (parent UUID points to missing entry)
  2. Injecting a synthetic tool_result for the orphaned tool_use
  3. Resuming the session

This is fragile and requires understanding the JSONL format.

Related Issues

  • #31328 (session becomes unresumable after JSONL writer drops assistant entry — closed as stale)
  • #21321 (tool-use concurrency 400 mid-session)

extent analysis

TL;DR

Implementing an atomic write pattern for session persistence is likely to fix the issue of Claude Code sessions becoming permanently unresumable due to tool use concurrency issues.

Guidance

  • Verify the issue by checking the JSONL session file for orphaned tool_use blocks without matching tool_result blocks, indicating non-atomic writes.
  • To mitigate the issue, consider implementing the suggested fix of writing session data to a temporary file, syncing it, and then renaming it to the session file, ensuring atomicity on POSIX systems.
  • As a temporary workaround, manually repairing the JSONL by injecting synthetic tool_result entries for orphaned tool_use blocks may allow session resumption, but this approach is fragile and requires understanding the JSONL format.
  • Review related issues (#31328 and #21321) for potential insights into similar problems and their resolutions.

Example

import os
import json

# Example of atomic write pattern
def write_session_data(data, session_file):
    temp_file = session_file + '.tmp'
    with open(temp_file, 'w') as f:
        json.dump(data, f)
    os.fsync(f.fileno())
    os.rename(temp_file, session_file)

Notes

The provided example is a simplified illustration of the atomic write pattern and may need adjustments based on the actual implementation and programming language used in the Claude Code CLI.

Recommendation

Apply the workaround of manually repairing the JSONL file until the atomic write pattern fix can be implemented, as it allows for some sessions to be recovered, albeit with fragility and the need for JSONL format understanding.

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

claude-code - 💡(How to fix) Fix Session JSONL corruption from non-atomic writes during concurrent tool execution [1 comments, 2 participants]