On Claude Code 2.1.317, a claude -p run or a claude mcp list that finds ~/.claude.json unparseable copies it into backups/, writes a 258-byte default in its place, and exits 1. The next run starts on that default, with no MCP servers and no trusted folders, and says nothing about it. A comment in the file, a file cut off mid-write, an empty file, and an empty file with backups present all ended the same way. An interactive start shows a dialog and leaves the file alone.
The bug has been filed three times since June under the data-loss label, was reproduced by Anthropic's own triage bot on 18 August, and was closed by a stale-issue script on 20 September. The 2.1.318 changelog, published at 21:55 UTC on 3 November, cites that closed issue and says a non-interactive start now fails, prints the restore command, and leaves the file as it is. The same reset was fixed once before, in 1.0.31, in June 2025.
On this Mac the file is 619 KB: 124 top-level keys, 221 project entries of which 160 are trusted, 8 user-scope MCP servers. The restore hint on 2.1.317 names the newest backup without checking that it parses, and in one of four batches of 40 parallel claude mcp add calls, a server that printed "Added" was not in the file afterwards. 2.1.318 itself was not run here: the auto-updater had not fetched it, and this environment refused a direct download.
What a headless start does on 2.1.317
The setup was a throwaway CLAUDE_CONFIG_DIR with a small valid config: three user-scope MCP servers, three project entries, two of them trusted, numStartups at 42. I damaged it four ways and started the installed 2.1.317 binary headless each time, with claude -p 'reply with the single word ok' --model haiku --output-format json.
Every damaged start printed the same three things to stderr: "Claude configuration file at … is corrupted: JSON Parse error: Unrecognized token '/'", then "The corrupted file has been backed up to: …/backups/.claude.json.corrupted.1793780402279", then "Configuration error in …". Exit code 1, nothing on stdout. The live file afterwards was 258 bytes and six keys: four migration flags, an empty seenNotifications, and a freshly generated userID. No mcpServers, no projects.
The second start on that directory is the part that matters. It ran without complaint, and claude mcp list answered "No MCP servers configured. Use claude mcp add to add a server." A cron job, a CI step, or a desktop launcher that retries after a non-zero exit gets a working Claude Code with a new identity and none of the state. The exit 1 is the only signal, and only the first attempt gives it.
| Input, all on 2.1.317 | What happened | Live file after |
|---|---|---|
/* my note */ inside valid JSON, headless -p |
corrupted, backed up, exit 1 | 258-byte default |
| file cut at 60% of its length | same | 258-byte default |
| 0-byte file, no backups | "Unexpected EOF", backed up, exit 1 | 258-byte default |
| 0-byte file, a good older backup and an empty newer one | restore hint names the empty backup | 258-byte default |
| cut-off file, one good older backup | hint names the good backup, then a backup of the broken file is written 7 ms later | 258-byte default |
cut-off file, claude mcp list |
same reset | 258-byte default |
cut-off file, claude --version |
prints 2.1.317 | untouched |
| cut-off file, interactive under a pseudo-terminal | dialog with two options | untouched after 12 s |
second -p on a reset directory |
runs, no error | unchanged |
valid file, two -p runs in a row |
run one rewrote it (802 to 2,111 bytes, new inode), run two did not | |
file and directory read-only, mcp add and mcp remove |
exit 1, "was not saved" | unchanged |
40 parallel mcp add -s user, four batches |
160 exits of 0, 159 servers in the files |
Under script, 2.1.317 drew a box: "Configuration error … Choose an option: 1. Exit and fix manually, 2. Reset with default configuration", and after 12 seconds the file was byte for byte what I had put there. Without a terminal, the same code takes option 2 on your behalf.
What you would lose
My own ~/.claude.json is 619,542 bytes: 124 top-level keys, the account record, 221 project entries of which 160 carry an accepted trust dialog, 8 user-scope MCP servers, and the 22 claude.ai connectors this account has ever attached. The default keeps none of it, not even numStartups.
Recovery exists. Claude Code keeps the five newest .claude.json.backup.<ms> files in ~/.claude/backups/ plus every .corrupted.<ms> copy. On this machine the five span 23:04 last night to 09:15 this morning, because an interactive session rewrites the file often. Two details complicate the restore. The reset writes a backup of the broken file 7 milliseconds after the .corrupted copy, so the newest backup after a reset is the broken file again. And the hint picks the newest backup by name: with a planted empty newest backup, it told me to cp the empty file over the live one.
The paper trail
The changelog for 1.0.31, on 20 June 2025, reads "Fixed a bug where ~/.claude.json would get reset when file contained invalid JSON." It came back.
Issue 69354 was opened on 18 June 2026 against 2.1.142 on macOS, title "claude.json silently overwritten when file contains block comments (/* */)..LOST my COMPLETE MCP SERVES", labels bug and data-loss, closed as stale on 11 August. Issue 73590 followed on 2 July from Windows: 45 .corrupted files between 11 April and 1 July, four of them zero bytes, and a live file with an empty mcpServers. Closed as a duplicate on 23 August.
Issue 87551 was opened on 18 August with the first issue's URL as its title and "Issue still exists" after it. Thirty-two minutes later Anthropic's claude[bot] posted that it had reproduced the report on 2.1.234 on Linux: the interactive start stops at the dialog, and a non-interactive start "prints 'configuration file … is corrupted' to stderr and then rewrites ~/.claude.json with defaults". The issue carried the labels data-loss and reproduced. On 20 September a GitHub Actions job closed it: "inactive for too long". The 2.1.318 line that fixes it cites that number.
What 2.1.318 says, and what I could not run
The 2.1.318 changelog has six lines about this file. A non-interactive start that can't parse it now fails, says how to restore, and leaves it. An empty file with no backup starts as if the file were missing. The restore command no longer names an empty or cut-off backup. Saves on shared network home directories are "less often deleted, briefly emptied or replaced by a near-empty or older copy". Unattended runs stop rewriting the file when nothing in it changed. And retention cleanup takes a fresh backup before deleting the last good one.
I did not get to run any of them. The native auto-updater had not fetched 2.1.318 by 08:30 UTC, the Desktop app bundles a 2.1.317 built for its Linux VM, and the sandboxed session this was written in refused a direct download from the release bucket. The settings page in the docs, updated at 01:46 UTC today, now says "a -p run prints the error and exits". That is the 2.1.318 behaviour. On 2.1.317 it prints the error, exits, and leaves a different file behind.
One line has a 2.1.317 starting point worth recording. The read-only case already fails loudly: with the file and its directory read-only, claude mcp add and claude mcp remove exit 1 and print "MCP server "newsrv" was not saved to … If that file is read-only or protected by a sandbox, make it writable". The 2.1.318 line is about shared network homes, which I don't have.
The lock line is the one with a number. 2.1.318 says claude mcp add and remove now wait for the config lock or exit 1, "though another job's save can still replace a saved server". On 2.1.317, 12 parallel adds landed 12 for 12. Four batches of 40 gave 160 exits of 0, each printing "Added stdio MCP server … to user config" and "File modified", and 159 servers in the files. srv35 in the first batch printed both lines and is not there. After the update, the number to watch is how many exit 1, because the one that goes missing still prints success.
Until the update lands
Run claude --version. If it says 2.1.317 or lower and anything on the machine starts Claude Code without a terminal, look in ~/.claude/backups/ for .claude.json.corrupted.* files. Each one is a reset that already happened. Restore from the newest backup that parses, which python3 -m json.tool will tell you, not the newest by name. And keep comments out of the file; it is strict JSON, and two of the three reports started with one.
Checks ran on 4 November between 08:20 and 08:28 UTC on macOS with the installed native 2.1.317. One real call to Haiku 5.5 to confirm the headless result shape, $0.01. Everything else never reached the model.