Custom subagents fail to register after cold start when settings.local.json grows very large (348KB / 2438 valid permission entries) -- fixed by removing the file
Summary
After a genuine full cold start (application fully closed and the process killed from the task list, not a resume), all custom subagents defined in .claude/agents/*.md failed to register — Agent tool dispatch for any custom subagent_type returned only the built-in types (claude, claude-code-guide, Explore, general-purpose, Plan, statusline-setup), none of the 10 real project-defined agents. We isolated this to the project's .claude/settings.local.json file: moving that file out of .claude/ and restarting fixed it immediately — all 10 custom agents registered correctly on the next cold start. We could not find a documented mechanism that explains why, and we'd like your team's help finding the actual root cause, since we don't currently have a way to determine whether this was caused by something in our own configuration, or by the version update that landed in the same window (see below).
Environment
- Claude Code version:
2.1.237(confirmed viaclaude.exe --version) - OS: Windows 10 Pro (10.0.19045)
- Install evidence of a same-night update:
%APPDATA%\Claude\claude-code\contains both a2.1.235and a2.1.237directory, both timestamped 2026-08-20 23:11 — i.e. an update appears to have landed the night before the failure was observed. We do not know for certain which version was active during the working session earlier that day versus the failing session the next morning, only that both version directories exist with that timestamp and2.1.237is what's active now. - 10 custom subagents defined in the project's
.claude/agents/*.md— 5 existed and worked reliably for over a week (oldest dated 2026-08-03), 5 more were added the prior afternoon (2026-08-20, ~13:55 local) via a real git commit to that directory (.claude/is itself a separate, small git repo nested at the project root, with no configured remote). - Project's tracked
.claude/settings.json(1.4 KB) has nopermissionskey at all — onlyhooks(SessionStart, PreToolUse ×2, SessionEnd, alltype: command).
What we ruled out (with evidence)
We suspected the prior afternoon's changes to .claude/ might be the cause, so we investigated each one directly:
- New agent file content/encoding: all 10
.claude/agents/*.mdfiles checked byte-for-byte — no BOM, consistent LF line endings, well-formed YAML frontmatter (name/description/toolsall present and correctly formatted). No difference in shape between the 5 that worked for a week and the 5 added the prior day. - A new tool grant (
Skill) introduced only in the 5 new agent files: this was our leading hypothesis for a while — every new agent'stools:line includedSkill, absent from all 5 pre-existing agents, a perfectly clean natural experiment. We fetched your own current sub-agent documentation directly to check, andSkillis explicitly documented as a valid subagent tool, and per that same documentation an unrecognized tool name in one file's frontmatter wouldn't affect other files anyway (independent per-file processing is documented). Ruled out. settings.jsondiff from the prior day (two new hook entries: aRead|GrepPreToolUse matcher, aSessionEndhook): valid JSON, structurally mirrors the existing hook pattern exactly. No documented connection between hooks and agent-directory scanning that we could find.- A subagent count limit: not documented anywhere we could find, and going from 5 to 10 agents seems like a very small number to hit any real limit.
The one thing that reliably reproduces the fix
.claude/settings.local.json (personal, gitignored, auto-managed by Claude Code itself) had grown to 348 KB, with a permissions.allow array containing 2,438 entries — confirmed to be syntactically valid JSON (parsed cleanly with JSON.parse, checked independently twice). The entries were not generalized rules like Bash(git *); they were thousands of ultra-specific, one-off, exact-literal full command strings (unique script paths, unique inline code, unique embedded timestamps), each apparently persisted individually. We confirmed the array grows continuously in real time — a new entry gets appended essentially every time a novel Bash command runs, with no deduplication or generalization, seemingly by design under whatever permission mode this session runs in (no permissions.defaultMode is set anywhere in this project's tracked or global settings, so per your own documented mode-selection order, this session should be running on the built-in default, which for a paid-plan terminal session is auto mode).
The test: we moved settings.local.json out of .claude/ entirely (backed up, not deleted) and did a second full cold restart. Result: all 10 custom agents registered correctly.
What we'd like your help understanding
- Why would a large-but-valid
permissions.allowarray cause custom subagent discovery to silently fail at startup, while the rest of the session (hooks, basic tool use) works fine? Is there an internal size/complexity limit or parsing budget we're hitting? Is agent discovery on a shared code path with settings merging that has an undocumented failure mode? We could not find this documented anywhere in your current docs (/docs/en/settings,/docs/en/permission-modes,/docs/en/sub-agents). - Is the version update that landed the same night (2.1.235 → 2.1.237) relevant at all? We have no way to determine from our side whether this is a config-size issue, a regression introduced in that update, or unrelated.
- If there is a real size/count limit somewhere, it would be extremely valuable to have it documented (and ideally: a startup warning or graceful degradation — e.g. "N custom agents failed to load because settings exceeded X" — rather than a silent, total loss of every custom agent with no indication anything went wrong).
Why this matters to us
This session runs entirely on custom subagents for a real internal governance/review workflow (adversarial QA review, requirements analysis, process-health audits) — losing all of them silently, with the only symptom being "Agent type not found" the next time we tried to use one, is a real reliability risk for anyone building on top of the Agent tool with custom personas. We'd like a real root cause, not just our own empirical workaround, since we can't be confident our workaround (keeping settings.local.json small) actually addresses the real mechanism versus just avoiding it by luck.
Happy to provide the actual settings.local.json (or a representative sample) if that would help reproduce this on your end.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗