CLAUDE LABJP
DESIGN — Claude Design gets a major update: design-system imports, direct canvas editing, and more export formatsCODE — Claude Design can start from your local codebase and hand a design off to Claude Code to implementFABLE — Fable 5, a Mythos-class model made safe for general use, is now available in Claude Code v2.1.170FIX — Mid-stream connection drops now preserve partial responses instead of showing a raw errorSCROLL — A new wheelScrollAccelerationEnabled setting disables mouse-wheel scroll acceleration in fullscreenTIER — The Claude Design beta is available to Pro, Max, Team, and Enterprise customersDESIGN — Claude Design gets a major update: design-system imports, direct canvas editing, and more export formatsCODE — Claude Design can start from your local codebase and hand a design off to Claude Code to implementFABLE — Fable 5, a Mythos-class model made safe for general use, is now available in Claude Code v2.1.170FIX — Mid-stream connection drops now preserve partial responses instead of showing a raw errorSCROLL — A new wheelScrollAccelerationEnabled setting disables mouse-wheel scroll acceleration in fullscreenTIER — The Claude Design beta is available to Pro, Max, Team, and Enterprise customers
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-code120settings7configuration5troubleshooting86

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-05-21
Claude Code Hook `command timed out`: Timeout Settings and Split-Execution Patterns That Actually Work
Fix Claude Code's `command timed out` hook failure without just bumping the timeout. Includes practical split-execution, detached background jobs, and a settings.json layout that keeps your session fast.
Claude Code2026-06-10
When git add -A Sweeps Up .bak Backups — The Quiet Trap of In-Place Fix Scripts
How .bak backups left by sed -i and homegrown --fix scripts get silently swept into production by git add -A, why it is so easy to miss, and how scoped adds and .gitignore close the gap for good.
Claude Code2026-06-09
When Yesterday's Article Bleeds Into Today's — The Stale Fixed-Name Temp File Trap
In a Claude Code automation pipeline, a fixed-name temp file kept stale content from the previous run and leaked old body text into a completely different article. Here is why the write fails silently, and how unique names plus a post-write grep check prevent it.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →