Auto-mode classifier doesn't fall back when its model is unavailable; CLAUDE_CODE_AUTO_MODE_MODEL is ignored
Summary
When the session's main model hits a capacity event, the main loop falls back to another model and keeps working — but the auto-mode permission classifier does not fall back. It keeps requesting the unavailable model and fails closed, denying every side-effectful Bash/Write/Edit with:
claude-fable-5[1m] is temporarily unavailable, so auto mode cannot determine the safety of Bash right now. Wait briefly and then try this action again. ...
The result is the worst of both worlds: the session is alive (on the fallback model) but cannot do any work. We hit this across two capacity events: 2026-06-06 (main = claude-opus-4-8[1m], classifier on the same model) and 2026-06-10 (main = claude-fable-5[1m], classifier on Fable), 90+ denials in transcripts.
This is the root-cause companion to several symptom reports: #63819, #63873, #67089, #62170, #38618, and the fail-open proposal in #67519.
Environment
- Claude Code 2.1.170, Linux, Max plan
model: "claude-fable-5[1m]", auto permission modepermissions.allowincludesBash(*)(intentionally ignored by auto mode — see below)
Root-cause analysis (binary inspection of 2.1.170 + --debug-file probes)
1. Classifier model selection never falls back. Decompiled selection logic (Rr7 in the 2.1.170 bundle):
classifierModel =
statsig("tengu_auto_mode_config").modelByMainModel[mainModel] // server mapping
?? statsig("tengu_auto_mode_config").model // server global
?? (isNewFamily(mainModel) ? (ANTHROPIC_DEFAULT_OPUS_MODEL ?? opus48) + "[1m]"
: mainModel) // default: ride the main model
There is no availability check and no retry-on-sibling. Whatever this resolves to, every classifier request targets it; if it 529s, the classifier is down even though the main loop has already fallen back successfully.
2. Unavailability fails closed by server-side flag. The handler has both branches:
if (W.unavailable) {
if (statsigGate("tengu_iron_gate_closed", /* default */ true))
return deny // "temporarily unavailable, so auto mode cannot determine the safety..."
return fallBackToNormalPermissionHandling // fail open — exists, but gated off
}
The fail-open path to normal static permission handling already exists in the binary but is unreachable for users (Statsig gate, default true, no client override).
3. Static allow rules can't serve as an escape hatch. Auto mode deliberately discards broad Bash rules at parse time — debug log: Ignoring dangerous permission Bash(*) from ~/.claude/settings.json (bypasses classifier). Reasonable in normal operation, but during a classifier outage it means there is no path to run any non-read-only Bash at all.
4. CLAUDE_CODE_AUTO_MODE_MODEL is dead. The env var is registered in the env-var registry but is never consulted by the selection logic above. Probe-verified: with CLAUDE_CODE_AUTO_MODE_MODEL=claude-sonnet-4-6 set, debug still shows classifier_request_started ... model=claude-opus-4-8[1m]. Either wire it up or remove it.
5. The only working client-side knob is too blunt. ANTHROPIC_DEFAULT_OPUS_MODEL=claude-opus-4-7 does redirect the classifier (probe-verified: classifier_request_started ... model=claude-opus-4-7[1m]) — but it remaps the "opus" alias CLI-wide (subagents, /model opus), so it's unusable as a targeted fix.
Suggested fixes (any one of these resolves it)
- Make the classifier inherit the main loop's fallback behavior — if the main request path can fall back during a capacity event, the safety classifier should too.
- Honor
CLAUDE_CODE_AUTO_MODE_MODELas an explicit override in the selection chain. - Fail open to normal static permission handling when the classifier is unavailable (the branch already exists) — or at minimum to an interactive prompt when a user is present, per #67519.
Workaround we settled on
"permissions": { "disableAutoMode": "disable" } — drops back to static rules + defaultMode entirely. Works, but gives up the classifier layer altogether, which is presumably not the intended trade-off. Worth documenting either way; it appears in the settings schema but not in the docs.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗