[BUG] Invalid MCP entry in ~/.claude.json: unattributable error, paused transcript cleanup, and an agent permission-prompt loop

Status Fixed / completed
Reported on v2.1.207
Maintainer reply ✓ Yes — bcherny
Activity 4 comments · opened Jul 13, 2026 · closed Oct 12, 2026
💡 Likely answer: A maintainer (bcherny, collaborator) responded on this thread — see the highlighted reply below.

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

A third-party app (BrowserOS.app, a Chromium-fork agentic browser) self-registers an MCP server into ~/.claude.json on every launch:

"mcpServers": { "browseros": { "url": "http://127.0.0.1:<port>/mcp" } }

The entry has no type field, so it is invalid (url-based servers require type: "http" or "sse"). The app also rewrites the entry while running, so user deletions don't stick. That external behavior is BrowserOS's fault and is being reported to them separately — but it exposed three Claude Code issues that will hit anyone whose config gets an invalid MCP entry:

1. The validation error names no file or key.
The startup/config warning reads Found invalid entries in: . — the filename is empty because MCP validation errors carry no .file. It took days to trace the warning to a single mcpServers key in ~/.claude.json. Please include the file path and the offending key in the message.

2. One invalid entry silently pauses transcript retention cleanup.
While the settings error existed, transcript retention cleanup did not run — 1,069 transcript files accumulated before we found the cause. A single malformed MCP entry shouldn't halt unrelated maintenance, and if it must, the pause should be surfaced to the user.

3. The combination drives agents into a permission-prompt loop.
Each new session, the agent sees a broken config, does the reasonable thing, and asks for write permission to repair ~/.claude.json. The external app then reasserts the entry, and the next session repeats the request — with no memory of the previous attempt. The user experiences this as the agent "going crazy," asking to write the settings/config file over and over while they deny it repeatedly. A "this entry changed outside Claude Code since last session" signal would let agents (and humans) distinguish a reasserting external writer from a corrupted file and stop fighting it.

What Should Happen?

  1. The config-validation warning names the file and the offending key — e.g. Found invalid entries in ~/.claude.json: mcpServers.browseros (url-based server missing "type") — instead of Found invalid entries in: . with an empty filename.
  2. Transcript retention cleanup keeps running when an unrelated settings entry is invalid — or, if it must pause, it says so visibly instead of silently accumulating transcripts.
  3. MCP entries rewritten by external processes are flagged (e.g. "modified outside Claude Code since last session") so users and agents can recognize a reasserting third-party writer instead of re-attempting config repairs every session.

Error Messages/Logs

Found invalid entries in: .

Steps to Reproduce

Repro

  1. Install a BrowserOS.app release from before mid-July 2026 and launch it (or manually add the malformed entry above to ~/.claude.json).
  2. Start Claude Code: observe Found invalid entries in: . with no filename under /config → Status.
  3. Leave the state in place for days: observe transcript cleanup not running.
  4. Delete the entry while BrowserOS runs: observe it reappear; watch successive agent sessions request config-write permission to fix it.

Observed 2026-07-09 → 2026-07-13; fully resolved only by uninstalling BrowserOS.

Claude Model

Other

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

Claude Code 2.1.207, macOS (Darwin 25.5.0)

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Other

Additional Information

<img width="1291" height="858" alt="Image" src="https://github.com/user-attachments/assets/a6d9efa0-cfbf-4364-bb73-32fffd00bdf1" />

This one looks this way because Fabel under infinite loops of echo tried to help and missed a simple thing
<img width="1196" height="932" alt="Image" src="https://github.com/user-attachments/assets/dc8d35dc-6f7f-4c4f-ae7f-5335798cbf5f" />

Human impact, for triage weighting: during diagnosis this failure mode derailed Claude Desktop three separate times while the user was trying to explain what they were finding — each fresh context re-encountered the broken config mid-conversation and pivoted to trying to fix it. Reading the agents' visible reasoning while they fixated on the config made it worse, not better — the internal monologue read as suspicious and adversarial to the user. The cumulative effect over several days was the user genuinely believing every agent on the machine had been compromised and was acting against them. A config error whose symptom is "my agents keep demanding write access and won't take no for an answer" damages trust far beyond its technical severity.

View original on GitHub ↗

3 Comments

thalys · 3 months ago

Had to yank out one of the images because I came to recheck and had my originSessionId

it was a funny day yesterday, Fabel Desktop saying good bye mid session sending me to sleep, then imediately saying oh hello good morning

bcherny collaborator · 1 month ago

Tested on 2.1.233 (Linux) with a fresh config containing your exact malformed entry ("browseros": {"url": ...} with no type) in ~/.claude.json.

  1. Confirmed / reproduced on 2.1.233: /status shows ⚠ Found invalid entries in: . with an empty file name — we'll fix that message to name the file and offending key. Meanwhile, claude doctor from the shell already pinpoints it (it prints mcpServers.browseros: Skipped — MCP server "browseros" has a "url" but no "type"; add "type": "http"), so that's the fastest way to locate an entry like this today.
  2. Transcript cleanup: recent releases (including 2.1.233) narrowed this — cleanup now only pauses when the retention setting itself can't be determined reliably (unparseable settings file, or cleanupPeriodDays explicitly set alongside errors), and when it does pause, /status says so explicitly instead of pausing silently.
  3. Flagging config entries rewritten by an external process is a fair feature request — we're considering how to surface "changed outside Claude Code" signals.

Sorry about the multi-day debugging ordeal this caused — the empty filename made a small problem look like a big one, and that's exactly what we'll fix. Keeping this open to track it.

🤖 Generated with Claude Code

marcindulak · 19 days ago

For your information: the label reproduced on this issue does not prevent it from becoming stale and eventually auto-closed. See https://github.com/anthropics/claude-code/issues/87647 for details, and consider upvoting that for visibility.

This means to avoid auto-closing, this issue needs to acquire at least 10 thumbs up, or get new comments every time before the 14 days stale bot interval expires.

Showing cached comments. Read the full discussion on GitHub ↗