claude-code - 💡(How to fix) Fix Session JSONL corrupted by non-atomic append when process killed mid-write — `--resume` fails with JSON parse error [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#52387Fetched 2026-04-24 06:08:32
View on GitHub
Comments
1
Participants
2
Timeline
6
Reactions
0
Timeline (top)
labeled ×5commented ×1

When the Claude Code process is terminated mid-write to its session JSONL (e.g. SIGKILL from parent, stdio pipe closed on VS Code Remote-SSH disconnect, laptop sleep breaking the tunnel), the partially-written record leaves a truncated stub on disk. The next append then starts writing from the same file position with no newline separator, producing two concatenated JSON objects on a single line that parse as neither. claude --resume <session-id> fails with a cryptic JSON Parse error: Expected ':' before value in object property definition and the session cannot be resumed.

Error Message

When the Claude Code process is terminated mid-write to its session JSONL (e.g. SIGKILL from parent, stdio pipe closed on VS Code Remote-SSH disconnect, laptop sleep breaking the tunnel), the partially-written record leaves a truncated stub on disk. The next append then starts writing from the same file position with no newline separator, producing two concatenated JSON objects on a single line that parse as neither. claude --resume <session-id> fails with a cryptic JSON Parse error: Expected ':' before value in object property definition and the session cannot be resumed. Minor but surfaces badly. Only the last record is ever affected, but the resume failure shows up as a JSON parse error with no obvious next step, and losing the active conversation context is disruptive enough that users blame the disconnect rather than a file-write bug.

  • #49876 — similar family (non-atomic JSONL appends), different manifestation: null-byte runs on WSL2 causing silent context truncation. Ours is a single-process kill on Linux/Remote-SSH causing loud parse-error failure.

Root Cause

When the Claude Code process is terminated mid-write to its session JSONL (e.g. SIGKILL from parent, stdio pipe closed on VS Code Remote-SSH disconnect, laptop sleep breaking the tunnel), the partially-written record leaves a truncated stub on disk. The next append then starts writing from the same file position with no newline separator, producing two concatenated JSON objects on a single line that parse as neither. claude --resume <session-id> fails with a cryptic JSON Parse error: Expected ':' before value in object property definition and the session cannot be resumed.

Fix Action

Workaround

External repair script that validates the JSONL line-by-line, locates the inner {" split boundary on the one corrupt line, keeps whichever half is valid JSON, and drops the truncated stub. Safe to run idempotently. Happy to share the ~100 lines of Python if useful.

Code Example

{"type":"pr-link","sessionId":"<redacted>","prNu{"parentUuid":"<redacted>","isSidechain":false,"promptId":"<redacted>","type":"user", ...}
RAW_BUFFERClick to expand / collapse

Summary

When the Claude Code process is terminated mid-write to its session JSONL (e.g. SIGKILL from parent, stdio pipe closed on VS Code Remote-SSH disconnect, laptop sleep breaking the tunnel), the partially-written record leaves a truncated stub on disk. The next append then starts writing from the same file position with no newline separator, producing two concatenated JSON objects on a single line that parse as neither. claude --resume <session-id> fails with a cryptic JSON Parse error: Expected ':' before value in object property definition and the session cannot be resumed.

Environment

  • Claude Code VS Code extension 2.1.118 (linux-x64); binary 2.1.117 / 2.1.118
  • Linux remote accessed via VS Code Remote-SSH
  • Trigger in our case: Remote-SSH tunnel drop over Tailscale / laptop sleep while Claude was streaming a response

Expected

Session files should remain parseable as newline-delimited JSON regardless of when the process is terminated. A partially-written record should be either fully absent or fully present — never a truncated stub followed by another record on the same line.

Actual

Example corrupt line (redacted, one bad line out of ~2800):

{"type":"pr-link","sessionId":"<redacted>","prNu{"parentUuid":"<redacted>","isSidechain":false,"promptId":"<redacted>","type":"user", ...}

The first ~74 bytes are a truncated pr-link record whose write was cut off at "prNu. The subsequent record was then appended to the same line with no separator. JSON.parse fails on the whole line; --resume bails out. Only the last-written line is corrupt — all prior records parse correctly.

Proposed fix

Make record appends atomic. Minimal-change options:

  1. Build the full record bytes (record + trailing \n) in memory and issue a single write(2) on an O_APPEND fd. Much less likely to tear than buffered fwrite+fflush pairs.
  2. For larger records, write to a sibling .tmp and commit via rename-append.

Either prevents the "two records on one line" pattern.

Workaround

External repair script that validates the JSONL line-by-line, locates the inner {" split boundary on the one corrupt line, keeps whichever half is valid JSON, and drops the truncated stub. Safe to run idempotently. Happy to share the ~100 lines of Python if useful.

Severity

Minor but surfaces badly. Only the last record is ever affected, but the resume failure shows up as a JSON parse error with no obvious next step, and losing the active conversation context is disruptive enough that users blame the disconnect rather than a file-write bug.

Related issues

  • #49876 — similar family (non-atomic JSONL appends), different manifestation: null-byte runs on WSL2 causing silent context truncation. Ours is a single-process kill on Linux/Remote-SSH causing loud parse-error failure.
  • #20992 → #20637 — both closed as duplicates. About concurrent-writer races on macOS (~/.claude.json and subagent workloads). Ours is single-writer.

extent analysis

TL;DR

Make record appends atomic to prevent truncated stubs and concatenated JSON objects.

Guidance

  • Implement one of the proposed fixes: build the full record bytes in memory and issue a single write(2) on an O_APPEND fd, or write to a sibling .tmp and commit via rename-append.
  • Verify the fix by simulating a process termination during a write operation and checking that the resulting JSONL file remains parseable.
  • Consider implementing an external repair script to validate and repair corrupted JSONL files as a temporary workaround.
  • Review related issues, such as #49876, to ensure that similar problems are addressed.

Example

No code snippet is provided as the issue does not contain sufficient information to create a concrete example.

Notes

The proposed fixes assume a single-writer scenario, and the issue may still occur in concurrent-writer scenarios. The external repair script can be used as a temporary workaround, but it is recommended to implement one of the proposed fixes for a more robust solution.

Recommendation

Apply the proposed fix of making record appends atomic to prevent truncated stubs and concatenated JSON objects, as it addresses the root cause of the issue and provides a more robust solution.

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 corrupted by non-atomic append when process killed mid-write — `--resume` fails with JSON parse error [1 comments, 2 participants]