Auto-mode classifier: ~310s permission decisions that resolve to "Allowed" — the 30s classifier timeout never fires

Status Fixed / completed
Reported on v2.1.229
Maintainer reply None cached
Activity 1 comment · opened Aug 13, 2026 · closed Aug 13, 2026

Summary

On claude-opus-5[1m] in auto permission mode, individual tool calls sit between tool_use and tool_result for 307–329 seconds, then execute normally, with the UI reporting Allowed by auto mode classifier.

No permission prompt is shown. Nothing is blocked. The commands themselves execute in 1–2 seconds. The entire wait is pre-execution.

9 occurrences across 3 sessions on 2 consecutive days. In the worst session, 31m11s of a 46m09s session was spent in these stalls — 68% idle.

This is distinct from the known classifier-outage reports (see Relationship to existing issues below): those fail closed with "temporarily unavailable" and block the call. These resolve to allowed, after roughly 10× the documented 30-second classifier timeout.

Environment

  • Claude Code 2.1.229
  • Windows 11 (win32)
  • Model: claude-opus-5[1m] — 1M context auto-upgraded by subscription tier, not explicitly selected
  • Permission mode: auto (permissions.defaultMode: "auto")
  • Dates: 2026-08-12 and 2026-08-13 (UTC timestamps below)

Measurements

Each row is one tool_usetool_result gap taken from the session transcript JSONL. Commands are described generically.

| # | Session | Tool / command class | Wall time |
|---|---|---|---|
| 1 | A | Bash — cloud CLI describe (read-only) | 5m 29s |
| 2 | A | Bash — cloud CLI describe with --query (read-only) | 5m 08s |
| 3 | A | Read — a JSON config file inside the project | 5m 08s |
| 4 | A | Bashnpx tsc --noEmit | 5m 11s |
| 5 | A | Bash — heredoc file write (cat > file <<EOF) | 5m 07s |
| 6 | A | Bashgit fetch origin + git status + git log | 5m 08s |
| 7 | B | Bash — directory listing under ~/.ssh | 5m 05s |
| 8 | B | Bashclaude mcp list | 5m 12s |
| 9 | C | Bashgh pr view --json … (read-only) | 5m 11s |

Tight clustering: 305.3, 307.5, 308.0, 308.0, 308.5, 311.0, 311.1, 311.9, 329.5 seconds.

The wait is pre-execution, not execution

For row 6, the transcript records the tool's own execution time alongside the gap:

"durationMs": 1434

1.4 seconds of execution inside a 308-second wall time. Measured independently afterwards, the same command completed in 1.6s.

The enclosing turn was recorded as:

"type": "system", "subtype": "turn_duration", "durationMs": 747820

12m 28s for a turn whose actual model and command work totalled about two minutes.

Row 3 rules out the Bash tool timeout

One of the nine was a Read, which has no Bash timeout budget at all. The Bash tool's own budget in these sessions was 3 minutes (180s) — shorter than every observed stall, and it never fired. So this is not the tool-execution timeout.

Ruled out locally

  • Network / git: git fetch executes in 1.4–1.6s; ls-remote under 1s. A pass-through check of the same commands outside the stall windows showed no latency.
  • SSH auth: key requires no passphrase (authenticates under BatchMode=yes), host key trusted for months. No prompt was ever pending.
  • PreToolUse hooks: supplied by a third-party plugin; each declares "timeout": 5, and at most two match a Bash call — a 10s ceiling.
  • A hook library's advisory lock: mkdir-based, capped at 100 attempts × 50ms = 5s, then gives up. Fractional sleep verified working (GNU coreutils 8.32), so the || sleep 1 fallback that would make it 100s never fires.
  • Stop hooks: ~17s per turn across 5 hooks, but recorded separately as stop_hook_summary and not inside these gaps.
  • Waiting on the human: no permission prompt was displayed at any point. Confirmed by the user.

Why this looks like a distinct bug

  1. A documented timeout did not fire. #64533 establishes a 30-second classifier timeout that fails closed with Auto mode classifier unavailable, denying with retry guidance. These waits were ~10× that and resolved to allowed.
  2. Nothing was blocked, so deny-and-continue recovery had nothing to recover from.
  3. The outcome is a successful approval. A check that silently costs five minutes and then permits the action is worse for the user than either allowing or denying — there is no signal to react to, and no log left behind.

Relationship to existing issues

  • #64533 (closed, not planned) — closest match on latency, but the classifier there timed out at 30s and failed closed. Its first-byte data is the most relevant part: single-attempt TTFB stalls of 215s, 220s, 225s, 239s on claude-opus-4-8[1m], p99 219.9s / max 238.9s, with a pass-through proxy confirming the bytes arrived late from upstream.
  • #82653 — same [1m] Opus 5 classifier path, but the failure mode is "temporarily unavailable" blocking every Bash call, and the 3-strike fail-open never engaging.
  • #74351, #49535, #68437, #58222, #57735, #80716 — classifier unavailability or over-blocking. All fail closed.

None of them describe a long stall that ends in an approval.

Hypothesis

The wait may not be the classifier deciding slowly — it may be the classifier's own API request stalling on first byte, on the [1m] serving tier.

That reading fits both datasets: #64533's upstream-confirmed 215–239s single-attempt first-byte stalls on the [1m] tier, and the fact that once a byte finally arrives here the decision itself is entirely ordinary ("Allowed"). It would also explain the missing 30s timeout, since a stalled request is not the same code path as a classifier that answered "unavailable."

The figures here are consistently longer than #64533's (307–329s vs 215–239s), which may indicate a different boundary or additional queueing.

Questions

  1. Is there a timeout on the classifier request path, and should the documented 30s classifier timeout cover this case? If not, what bounds it?
  2. Can a classifier request fail fast — fall back to prompting the human — rather than stalling for minutes and then approving?
  3. Should classifier requests be served off the [1m] tier at all? Per the published design, Stage 1 is a single-token yes/no decision and Stage 2 is a short chain-of-thought whose prompt is largely cache-hit from Stage 1. Neither needs a 1M-token context window, yet routing them through that tier appears to inherit its queue characteristics — and because auto mode issues one classifier request per tool call, it is the highest-frequency victim of any latency there.
  4. Can classifier latency be surfaced — in the UI, or in a persistent log? There are currently no persistent CLI logs on disk, so past occurrences can only be reconstructed by diffing timestamps in the session JSONL.

Reproduction notes

Not deterministically reproducible. Probes run outside the stall windows return in 1–2s, including commands from the same families that had stalled hours earlier. The stalls appear in bursts and are indifferent to the command's risk: in session C, a gh pr merge that merged a pull request into the default branch cleared in 10.3s, while a read-only gh pr view issued 20 seconds later stalled for 5m 11s.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗