◉CLAUDE LABJP
●CODE 2.1.319 — Claude Code now moves MCP tasks to the background automatically, and a denyInsteadOfPrompting setting denies calls that would wait on a prompt●CONSOLE — Console IP allowlist is in beta (11/5): requests from addresses not on the list are refused●SONNET 4.5 — Retires on the Claude API on 11/30, 23 days left. Migrate to Sonnet 5.5●WINDOWS — Reports say hooks break silently only on Japanese-locale Windows; check the character encoding first●FAST — Opus 4.8 fast mode is deprecated and will be removed on 11/30. Migrate to Opus 5.5●NEW — I Put a Ten-Line Promise File at the To…●CODE 2.1.319 — Claude Code now moves MCP tasks to the background automatically, and a denyInsteadOfPrompting setting denies calls that would wait on a prompt●CONSOLE — Console IP allowlist is in beta (11/5): requests from addresses not on the list are refused●SONNET 4.5 — Retires on the Claude API on 11/30, 23 days left. Migrate to Sonnet 5.5●WINDOWS — Reports say hooks break silently only on Japanese-locale Windows; check the character encoding first●FAST — Opus 4.8 fast mode is deprecated and will be removed on 11/30. Migrate to Opus 5.5●NEW — I Put a Ten-Line Promise File at the To…
Articles/Claude Code
⟐ Claude Code/2026-06-18Intermediate

When a Broken settings.json Stops Claude Code From Starting — Safe Mode and How to Split Your Config

How to find which config layer is broken when a settings.json syntax error stops Claude Code from starting, recover in minutes, and structure your settings so an automated pipeline can't quietly break itself.

claude-code133settings9configuration10troubleshooting105

✦ Premium Article

A single stray comma in a config file once stopped Claude Code from starting at all. If you hit that even once, it changes how you think about configuration. As an indie developer I run a pipeline that updates four sites automatically alongside my apps, and one morning the scheduled run had quietly stalled — I'd left a trailing comma in a hooks block I appended to .claude/settings.json. There was an error, but which file in which layer caused it wasn't obvious. That feeling — minutes draining away on triage — is the real trap with configuration.

Recent versions of Claude Code added a behavior where, when it detects a broken config, it isolates that single file and keeps starting in a degraded "safe mode." That's convenient, but if you don't understand why your usual permission rules suddenly aren't applying, it creates a different kind of confusion. Here I'll lay out what happens when config breaks, where to start triaging, and — more importantly — how to structure your settings so an automated workflow doesn't break itself in the first place.

What Claude Code does when config breaks

The first thing to internalize is that Claude Code's configuration isn't all-or-nothing. Settings are loaded from several files, and higher-priority ones override lower-priority ones. From highest to lowest:

PriorityTypeTypical path
1 (highest)Enterprise managed policymacOS: /Library/Application Support/ClaudeCode/managed-settings.json
Linux: /etc/claude-code/managed-settings.json
2Command-line arguments--model, etc.
3Project personal settings.claude/settings.local.json
4Project shared settings.claude/settings.json
5 (lowest)User settings~/.claude/settings.json

This layered structure is exactly why the behavior on breakage feels counterintuitive. Older builds could refuse to launch when any file was malformed; recent ones quarantine the broken config instead. When Claude Code finds a file it can't parse as JSON, it drops that one file from the load set and keeps starting in safe mode using the remaining valid settings.

The easy misreading here is "it started, so my settings must be applied." In reality, the permissions.deny and hooks you wrote in the quarantined file are being ignored entirely. In an automated context that produces a half-working state: a command you meant to deny falls back to ask and blocks on approval, or a hook you expected never fires and only a log remains. The "scheduled run quietly stalled" symptom I hit was exactly this pattern — a nasty gotcha when it strikes a production pipeline.

Whether you booted into safe mode shows up in the warning at startup and in /doctor, which tells you which settings file it flagged. That's the fastest place to look. I've written up how to read /doctor itself in Triaging config trouble in three minutes with /doctor.

Pinpointing which layer is broken

Recovery starts with identifying the broken file. There are at most five settings files, so mechanically validating each one as JSON surfaces the culprit immediately. This is the one-liner I run first: it parses each file with jq in priority order and bluntly flags the ones that fail.

# Validate every settings file that could be loaded, as JSON.
# Only broken files are reported as "INVALID".
for f in \
  "/Library/Application Support/ClaudeCode/managed-settings.json" \
  "/etc/claude-code/managed-settings.json" \
  "$PWD/.claude/settings.local.json" \
  "$PWD/.claude/settings.json" \
  "$HOME/.claude/settings.json"; do
  [ -f "$f" ] || continue
  if jq empty "$f" 2>/dev/null; then
    echo "OK      $f"
  else
    echo "INVALID $f"
    # Show the error with line/column of the break
    jq empty "$f"
  fi
done

Expected output looks like this — only the broken file is INVALID, and jq tells you exactly where parsing fell apart.

OK      /Users/you/project/.claude/settings.json
INVALID /Users/you/.claude/settings.json
jq: error (at /Users/you/.claude/settings.json:14): Expected another key-value pair at line 14, column 3

At that point the offending file and line are settled. If jq isn't installed, Python's standard library does the same job.

# Fallback validation when jq is unavailable
python3 - "$HOME/.claude/settings.json" << 'PY'
import json, sys
path = sys.argv[1]
try:
    with open(path) as fp:
        json.load(fp)
    print("OK", path)
except json.JSONDecodeError as e:
    print(f"INVALID {path}: {e}")
PY

The most common triage mistake is forgetting the high-priority enterprise managed policy exists. On a team-provisioned Mac, /Library/Application Support/ClaudeCode/managed-settings.json overrides your ~/.claude/settings.json, so when "I edited my user settings but nothing changed," suspect that top-level file first. Command-line arguments like --model also win over settings, so check whether a stale flag lingers in your launch script.

✦

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
✦If a settings.json syntax error has ever left Claude Code refusing to start, you'll understand what safe mode actually does and be able to recover in minutes
✦You'll get the exact commands and steps to pinpoint whether the broken config lives in the enterprise, user, project, or local layer
✦You'll be able to split and pre-validate your settings.json so an automated pipeline never ships a broken config in the first place
Secure payment via Stripe · Cancel anytime
✦

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

Related Articles

⟐ Claude Code2026-11-03
When Claude Code dies with a Bus error on a shared home directory, check this before you turn off auto-update
Why Claude Code crashes with a Bus error on an NFS-style shared home, how the official cleanup rule and update switches work, and two small scripts to check your setup.
⟐ Claude Code2026-08-25
A One-Letter Typo in settings.json Is Ignored Without a Single Warning
I diffed claude doctor output between a settings.json with misspelled keys and a correct one. There was no difference at all. Here is what actually gets validated, what slips through, and a small check that catches typos before they cost you a day.
⟐ Claude Code2026-05-24
When Claude Code's Sequential Edits Cascade into Failure — Fixing 'old_string not found' and 'not unique' on the Same File
Run several Edits against the same file and the second or third one suddenly fails with 'not found', 'not unique' or 'modified since read'. Here is how to tell the three apart, a small script that counts matches first, and the correct formatter hook setup.