False positive corruption detection: .claude.json.corrupted files accumulate due to multi-process race condition

Resolved 💬 3 comments Opened Feb 18, 2026 by dvdarkin Closed Feb 22, 2026

Description

Claude Code's .claude.json corruption detection produces 100% false positives when multiple Claude Code processes run concurrently (e.g., main CLI + subagents, multiple IDE instances). Over 5 days of normal use, 55 .corrupted.* files accumulated in $HOME — every single one contained valid, well-formed JSON.

Root Cause Analysis

Analyzed all 55 corrupted files and identified the mechanism:

  1. Each Claude Code process generates a new random userID on startup. Across 55 files over 5 days, there were 27 unique userID values for the same user/machine.
  1. When Process A writes .claude.json, Process B reads it back and sees a different userID (and possibly different numStartups, tipsHistory, etc.) than what it last wrote → flags it as "corrupted."
  1. This cascades — within same-second clusters (5–200ms spread), multiple processes all detect each other's writes as corruption, each saving a .corrupted.* copy and writing their own version.

Evidence

Time clustering shows concurrent-process race condition

Files arrive in bursts at the same timestamp (millisecond precision):

| Timestamp cluster | Files | Spread | Pattern |
|---|---|---|---|
| 1771017698xxx | 4 files | 18ms | Different userIDs, identical content |
| 1771370494xxx | 5 files | 87ms | 3 files userID f5f1fc9632fd, 2 files 0189fca2e675 |
| 1771370569xxx | 7 files | 174ms | Mix of old (39KB) and new (118B) state |
| 1771437697xxx | 4 files | 37ms | 3 files one userID, 1 file different |

All "corrupted" files are valid JSON

Files analyzed: 55
Valid JSON: 55 (100%)
Actually corrupted: 0 (0%)

Orphaned temp file confirms atomic-write pattern

.claude.json.tmp.34072.1771153520052 — an orphaned temp file from a process that crashed/was killed before completing the rename step of the write-to-temp-then-rename pattern.

Environment

  • OS: Windows 11 Pro 10.0.26100
  • Claude Code version range: 2.1.29 → 2.1.45 (across the observation period)
  • Typical usage: CLI + subagents, sometimes multiple concurrent sessions

Impact

  • Disk clutter: ~55 files / 5 days (~10/day), totaling ~1.8 MB of redundant JSON snapshots
  • User confusion: "corrupted" filename suggests data loss when none occurred
  • No actual data loss: The valid .claude.json was always intact

Suggested Fixes

  1. Use a stable machine-level userID instead of regenerating on each startup — 27 different IDs for one user in 5 days defeats the purpose of an identifier
  2. Improve corruption detection to distinguish "another Claude Code process updated this file" (expected) from "the file is actually malformed" (not observed)
  3. Implement file locking (advisory lock file with PID ownership, or OS-level locks) to serialize writes
  4. Consider SQLite for settings persistence — it handles concurrent access natively

Reproduction

  1. Run multiple Claude Code sessions concurrently (or use features that spawn subagents)
  2. Wait for any process to write .claude.json
  3. Observe .claude.json.corrupted.* files appearing in $HOME
  4. Validate them with JSON.parse() — they will all be valid

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗