[Bug] Custom subagent crashes silently when `model: sonnet` — CLI Mo8/createInstance secondary crash hides original error
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?
What's Wrong?
A custom subagent defined in .claude/agents/{name}.md with model: sonnet enters a silent crash loop after a few normal tool calls. The subagent's next inference API call hangs for ~3 minutes, then the Bun-bundled CLI dumps minified source code (with leading line numbers like 503, 504, 505) to the user's terminal — this is a secondary crash inside the Mo8 / Ink.createInstance error-display path. The original error (whatever caused the 3-minute hang) is never persisted to the subagent's JSONL, never written to stderr, and never reaches the user. The subagent process is auto-respawned, but each restart writes only agent-setting / permission-mode entries with no message body and re-crashes immediately.
Re-defining the same agent with model: opus (no other changes — same body, same input) resolves the issue. The leading line numbers in the dump are JavaScript source line numbers, not HTTP status codes — they happen to land on 503/504, which masquerades as a gateway error and adds to the diagnostic confusion.
Environment: Claude Code 2.1.119, Linux Ubuntu (kernel 6.8.0-94-generic), bash, Bun-bundled CLI (stack frames at /$bunfs/root/src/entrypoints/cli.js). Account well within rate limits at failure time.
What Should Happen?
What Should Happen?
- The underlying error (API response status + body, or local runtime exception) should be persisted to the subagent's JSONL session file (~/.claude/projects/{encoded-project}/{session-uuid}.jsonl) before attempting Ink rendering — so a post-mortem is always possible.
- If Mo8 / Ink.createInstance throws during error rendering, the CLI should fall back to plain stderr.write(error.message) so the original error reaches the user instead of a minified source dump.
- After ≥2 consecutive subagent restarts produce zero content entries, the parent session should receive a structured [SUBAGENT_DEAD]-style signal and the subagent should stop being respawned indefinitely.
- Custom-agent rendering failures must not present as line-numbered minified source — that output pattern is indistinguishable from real HTTP error codes (e.g. 503: / 504:) and actively misleads diagnosis.
Error Messages/Logs
Error Messages/Logs
Tail of the dumped output observed in the user's terminal (last 10 stack frames; the secondary-crash call site):
- createInstance (/$bunfs/root/src/entrypoints/cli.js:502:249)
- Jv (/$bunfs/root/src/entrypoints/cli.js:484:58456)
- VOH (/$bunfs/root/src/entrypoints/cli.js:484:88642)
- oTH (/$bunfs/root/src/entrypoints/cli.js:484:87842)
- PD8 (/$bunfs/root/src/entrypoints/cli.js:484:86738)
- rTH (/$bunfs/root/src/entrypoints/cli.js:484:86558)
- jJ$ (/$bunfs/root/src/entrypoints/cli.js:484:83272)
- aH (/$bunfs/root/src/entrypoints/cli.js:484:6552)
- vH (/$bunfs/root/src/entrypoints/cli.js:484:5006)
- UH (/$bunfs/root/src/entrypoints/cli.js:484:5318)
The source dump above the stack frames includes (identifiable by symbol names):
- Mo8({error:H}) — the error-display React component
- Yo8.clean / parseLine / captureString — the stack-trace cleaner library
- f3 (Ink Box) / Fz (Ink Text) primitives
This points at a secondary crash while formatting a primary error for terminal display.
Subagent JSONL signature (path: ~/.claude/projects/{encoded-project}/{subagent-session-uuid}.jsonl):
// Last successful entry — Read tool returned a ~10 KB markdown file
{"type":"user","message":{"role":"user","content":[{"type":"tool_result",...}]},"timestamp":"2026-04-27T08:47:23.132Z","sessionId":"<uuid>","version":"2.1.119"}
// ~3-minute gap — zero entries
// Subagent process restart #1 — metadata only, no content
{"type":"agent-setting",...}
{"type":"permission-mode",...}
// Restart #2 — same pattern, immediate re-crash
{"type":"agent-setting",...}
{"type":"permission-mode",...}
Searches across the JSONL find zero matches for: is_error:true, tool_use_error, api_error, overloaded, Service Unavailable, Bad Gateway, Internal error. Default log directory ~/.claude/logs/ does not exist on this install (so no fallback log destination either).
Steps to Reproduce
Steps to Reproduce
▎ Reproduction is not deterministic per call. Observed across multiple sessions on 2026-04-27 with the same agent definition; some /review-feature invocations crashed, others completed. Likely dependent on transient sonnet-side capacity or specific token-shape conditions. The model: opus workaround was 100% effective in our testing once applied.
- Create a custom subagent definition file .claude/agents/test-coord.md:
---
name: test-coord
description: Test subagent for repro of silent crash
tools: Read, Glob, Grep, Bash, Write, TaskCreate, TaskUpdate, TaskList, SendMessage
model: sonnet
---
1. Role
[Detailed role definition — multi-phase coordinator with batch responsibilities]
2. Input format
[JSON spec describing N work items]
3. Internal tracking
[Variable definitions, update timing]
4–9. Phase 0–4 procedure
[Detailed phase rules, spawn-spec format, error classification, batch reporting]
10–12. Failure handling, references
[Escalation tables, doc pointers]
- File should be substantial — total ~400+ lines / ~25 KB. Short subagent bodies do not seem to trigger the issue. (We can share the exact file content privately if helpful — it is a workflow-coordinator definition unrelated to user data.)
- From a parent Opus session in any project that contains the agent file above, create a team and spawn the subagent via the Agent tool with a substantial prompt:
Agent({
subagent_type: "test-coord",
team_name: "test-batch-{stamp}",
name: "test-coord",
prompt: "<~3 KB JSON-formatted batch input listing 6 work items, plus 1–2 paragraphs of phase guidance>"
})
- The subagent (sonnet) performs (each completing successfully):
- 1× TaskCreate
- 1× TaskUpdate (status → in_progress)
- 1× Bash ls of a few project state directories
- 1× Read of one ~10 KB markdown file
- Observe: the subagent's next inference call hangs for ~3 minutes with no output.
- After the hang, the user's terminal (the tmux pane hosting the subagent) emits a long minified Bun source dump prefixed with line numbers (typically lines 502–505 of the bundled cli.js), starting with one of:
503 `)}function rF$(H,$,q,K,_){let A=Vq$(H);...
- or
504: `);if(!/^\s*at /.test(H[0])&&...
- The subagent process exits, is auto-respawned, and re-crashes immediately — only agent-setting / permission-mode entries accumulate in its JSONL with no message body.
- Verify reproduction signature: open ~/.claude/projects/{encoded-project}/{subagent-session-uuid}.jsonl and confirm a ~3-minute gap between the last tool_result entry and the first restart entry, with no is_error / api_error / tool_use_error anywhere.
- Workaround validation: change the agent definition's frontmatter from model: sonnet to model: opus (one-character delta). Re-run from step 2 with the same prompt. The subagent now completes the workflow normally — confirms the workload is fundamentally feasible and points to a sonnet-specific path or a sonnet/Bun renderer interaction.
Claude Model
Opus
Is this a regression?
No, this never worked
Last Working Version
_No response_
Claude Code Version
2.1.119 (Claude Code)
Platform
Anthropic API
Operating System
Ubuntu/Debian Linux
Terminal/Shell
WSL (Windows Subsystem for Linux)
Additional Information
_No response_
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗