Repository navigation
Description
Summary
A long Claude thread reached 96% of its context window (961,230 of 1,000,000 tokens). Claude reported auto-compact as enabled, yet the next turn failed 4 s after it started, and the chat panel showed only Claude turn failed (blocking_limit). That message doesn't say the context is full or what to do. BiBCode didn't compact or retry. The user had to recognise the cause, type /compact by hand, and resend. Messages sent after the failure queue behind the manual compaction. The profiler recorded nothing for the failed turn.
Environment
| Field | Value |
|---|---|
| BiBCode | 0.10.2, desktop (AppImage) |
| OS | Omarchy (Arch-based Linux), x86_64 |
| Mode | local |
| Provider | Claude Code 2.1.308, stream-json, 1M-token context window |
| Finding | none (provider turn failures raise no profiler finding) |
Evidence
- Thread token usage at 13:25:27 UTC:
usedTokens961,230,maxTokens1,000,000,compactsAutomatically: true(from Claude'sisAutoCompactEnabled). - The turn started at 13:30:18 and failed at 13:30:23 UTC. The session is now in
errorwithlast_errorClaude turn failed (blocking_limit).andlast_error_classprovider_error. - Claude's own transcript for that turn: one synthetic assistant message with
isApiErrorMessage: true,error: "invalid_request", textPrompt is too long. The transcript has no compaction boundary, so automatic compaction never ran. It wasn't a failed compaction: Claude then saysautomatic compaction failed: …. - In Claude Code 2.1.308,
blocking_limitsits withprompt_too_longandrapid_refill_breakeras the{ kind: "stop", cause: "context_limit" }terminal reasons. - Profiler events from 13:29 to 13:35 UTC: only
server.refreshProviderUsagetimings and client batches. Nothing marks the failed turn.
Suspected source
apps/server/src/provider/claude/runtime.rs:2654: with noerrorsand noapi_retryerror, the message falls back toClaude turn failed (<terminal_reason>)., which turns a context-limit stop into an opaque code.apps/server/src/provider/claude/protocol.rs:86:AssistantMessagedoesn't model Claude'serror/isApiErrorMessage, so thePrompt is too longtext never reaches the failure message.apps/server/src/provider/claude/usage.rs:63: BiBCode already knowsusedTokens,maxTokensandcompactsAutomatically, but nothing acts on a near-full window.
Reproduction
- Run a Claude thread until the context indicator approaches the window (here 96% of 1M).
- Send another message.
- The turn fails within seconds with
Claude turn failed (blocking_limit).Further messages also fail or queue until the user sends/compact.
Root-cause hypothesis
Claude Code stopped at its blocking context threshold without running auto-compact, even though auto-compact was enabled. That part is upstream behavior in headless stream-json mode, and its trigger is unclear. BiBCode treats the stop as a generic provider error, hides the actionable text, and has no recovery path. Confidence: high for the BiBCode handling (code paths above); low for why Claude skipped its own auto-compact.
Suggested fix direction
- Classify
blocking_limit,prompt_too_longandrapid_refill_breakeras a context-limit failure (its ownerrorClass). Show an actionable message such as "This conversation filled Claude's context window. Compact it to continue.", with a Compact action, and carry Claude's own text (Prompt is too long, orautomatic compaction failed: …). - Recover automatically: on a context-limit failure, send
/compactto the same session once, then redeliver the failed message. If compaction fails too, stop and show the actionable error; never loop. Consider a setting, on by default. - Guard proactively: when
usedTokens / maxTokenscrosses a high threshold (for example 95%) and the turn ends idle, compact before the next turn instead of waiting for Claude's blocking threshold. - Profiler coverage: record provider turn failures (redacted: provider, terminal reason, error class) so repeated context-limit stops raise a finding.
Activity
mubeda commentedon Oct 22, 2026
Docs follow-up, checked against the official Claude Code docs on 2026-10-22 (Claude Code 2.1.308, the latest release):
What is new:
blocking_limitwithout compacting. Root-cause hypothesis (medium): one turn's input carried the conversation past both thresholds at once. Claude's documented recovery (compact, then retry) didn't run in headless stream-json mode.-p/stream-json output the text staysPrompt is too long. The interactive form isContext limit reached · /compact or /clear to continue. BiBCode should show the interactive wording plus a Compact action.--autocompact <tokens>per launch, orCLAUDE_CODE_AUTO_COMPACT_WINDOW) to leave headroom on 1M models. Or compact proactively from theautoCompactThresholdthat the context-usage response reports.error,status: "compacting",autoCompactThreshold,terminal_reasonclasses) are tracked in Claude: adapter ignores Agent SDK error, compacting and threshold fields #161.mubeda commentedon Oct 22, 2026
The recovery proposed here can be provider-generic. Codex app-server 0.163 has
thread/compact/start(compact on demand, progress as acontextCompactionitem) and reportscontextWindowExceeded. OpenCode 2.1 hasPOST /api/session/{id}/compactandSession.Message.Compaction(running,completed,failed;reasonautoormanual). Per-provider gaps: Codex #162 and #163, OpenCode #164.merge: v0.11.0 upgrades and fixes (#177)
test(server): expect the provider reason on a failed OpenCode turn