[Bug] Custom subagent crashes silently when `model: sonnet` — CLI Mo8/createInstance secondary crash hides original error

Resolved 💬 3 comments Opened Apr 27, 2026 by BR-JAEHANKIM Closed May 12, 2026

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?

  1. 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.
  2. 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.
  3. 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.
  4. 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.

  1. 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]

  1. 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.)
  2. 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>"
})

  1. 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
  1. Observe: the subagent's next inference call hangs for ~3 minutes with no output.
  2. 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);...

  1. or

504: `);if(!/^\s*at /.test(H[0])&&...

  1. 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.
  2. 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.
  3. 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_

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗