[Bug] One transient advisor failure permanently latches the tool off for the whole session; distinct error causes flattened to generic "unavailable"
Summary
A single failed advisor call permanently disables the advisor tool for the rest of the session, even when the underlying failure is transient (rate pressure / load). The client surfaces one generic latched string — The advisor tool is unavailable. Do not try to use it again. — and never retries, so long-running sessions lose the advisor entirely after one bad moment.
Environment
- Claude Code 2.1.173 (also observed on 2.1.16x–2.1.17x)
- Linux (WSL2), terminal CLI
- Main model: Fable 5 and Opus 4.8 sessions both affected
Reproduction
- Run several concurrent Claude Code sessions on one account (e.g. an orchestrator session plus 4–6 worker sessions in tmux panes — typical subagent/fanout workload).
- In any session, have the model call
advisor()while the account is under concurrent load. - The call fails with
Advisor unavailable (unavailable). - Any later
advisor()call in that session — including minutes/hours later when the account is idle — immediately returnsThe advisor tool is unavailable. Do not try to use it again.without attempting the call.
Observed 4 independent latches across 4 different sessions in one afternoon under this workload. A fresh session on the same account immediately has a working advisor again, confirming the failure is per-session client state, not account/server state.
Expected
- Transient failures (rate-limit / overload class) should be retryable — at minimum on the next explicit
advisor()call, ideally with backoff. Only genuinely permanent conditions (e.g. unsupported model pairing) should latch for the session. - The surfaced error should preserve the underlying cause. The API distinguishes
advisor_tool_resulterror codes (e.g.prompt_too_long,too_many_requests,overloaded,execution_time_exceeded,unavailable), but the client flattens all of them into the same latched "unavailable" string, which makes the failure look random and undiagnosable from the transcript.
Actual
- One transient failure → advisor dead for the session lifetime.
- All error causes collapse into one generic string (related: #66784, which reports the same generic wording for the model-pairing case).
Impact
Long-running orchestration sessions (the sessions that most need a second-opinion pass) effectively cannot rely on the advisor: the heavier the (legitimate) concurrent workload, the more certain the advisor is to latch off early in the session. Current workarounds are restarting the session or wiring an external review fallback.
Suggested fix
Treat too_many_requests / overloaded / unavailable-class results as retryable (clear the latch on next call or after a cooldown), latch only on permanent conditions, and include the specific error code in the surfaced message.
Showing cached comments. Read the full discussion on GitHub ↗
3 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Not a duplicate — requesting this stays open.
advisor_tool_resulterror codes are flattened into the same generic string.Additional evidence gathered since filing (Linux/WSL2,
claude-fable-5, headless-pprobes, same flags and model, only context size varied, runs minutes apart):| Context before
advisor()call | Result ||---|---|
| minimal (no files read) |
ADVISOR_OK|| ~256KB filler read first |
ADVISOR_OK|| ~512KB filler read first |
ADVISOR_OK|| ~1.2MB filler read first |
Advisor unavailable (unavailable)|This independently corroborates #67609, which bisected the same failure on macOS to a ~100–122K-token transcript boundary. That is the
prompt_too_longclass — deterministic, but indistinguishable from every other cause once flattened to "unavailable".Size is not the only trigger. A fresh session at roughly 37K tokens failed with the identical string while the account had several concurrent sessions mid-inference; an identical tiny headless probe on the same account passed 13 minutes later. That is the rate/overload class, consistent with advisor invocations drawing from the same per-model rate-limit bucket as direct calls to the advisor model.
On the latch specifically: a plain
/compactdoes not clear it. Observed twice — context compacted back to ~133K tokens (below the size boundary), the nextadvisor()call visibly attempts ("Advising using Fable 5" spinner) and still returns unavailable. One session recovered only after a full out-of-context rollover followed by/compact; fresh sessions always recover. So the latch is session-sticky state that survives compaction.The two fixes requested in the issue body stand:
prompt_too_long,too_many_requests,overloaded, …) instead of one generic string.prompt_too_longshould clear when the transcript shrinks; rate/overload-class failures should be retryable on the next call or after a cooldown.Confirming this still reproduces on Claude Code 2.1.199 (later than the versions reported above), so it's not fixed yet.
Setup:
advisorModel:fableRepro:
advisor()call in the session failed with the generic"The advisor tool is unavailable. Do not try to use it again."advisorModelinsettings.json(toggled it, then set it back tofable) mid-session, hoping a config change would clear whatever caused the first failure.advisor()again in the same session: got the exact same string back essentially instantly, no visible retry/API round-trip delay.That instant, identical response on the second call (despite changing the on-disk setting in between) matches this issue's description exactly: the failure is per-session client state, not something a settings change or the server can clear once it's latched. A fresh session window is the only workaround so far, consistent with what's reported here.
Would be good to get the underlying
advisor_tool_resulterror code surfaced to the user instead of the flattened generic string, this makes it very hard to tell "transient/latched" apart from "actually misconfigured" (see #66784) or "classifier declined" (see #67306) without independently digging through GitHub for prior reports.