Repository navigation
Description
Summary
When a provider request fails server-side, the TUI session shows a bare Error: Error (generic name + generic message) with no indication of the actual failure type (rate limit, auth, model rejection). The real cause is only visible in the server log, making provider failures undebuggable from the UI.
Environment
- opencode version: 2.0.22 (homebrew
opencode-v2formula) - OS: Darwin 25.5.0 (darwin arm64)
- Terminal: xterm-kitty (TERM=xterm-kitty, COLORTERM=truecolor)
- Shell: /bin/zsh
- Install/channel: latest
- Active plugins:
@andrzejchm/[email protected](at time of report; also reproduced with a broken/absent auth plugin), localplugins/mnemoteca.js, localplugins/superpowers.js
Reproduction
- Configure an
anthropicmodel (e.g.anthropic/claude-opus-5-5) as an agent model. - Trigger any provider-side failure, e.g.:
- exhaust the Claude Pro/Max rate limit (429), or
- unload/break the auth plugin so requests fail with an authentication error, or
- use a model the account cannot access.
- Run a prompt in the TUI and wait for the session to fail.
Expected Behavior
The session shows the actual error — e.g. Rate limit exceeded / Authentication failed: ... / the provider's error message — so the user knows what to fix without leaving the UI.
Actual Behavior
The session header shows only:
Error: Error
with no further detail. Two distinct root causes both surfaced as the identical Error: Error:
AI.Error.RateLimit(429 from Anthropic) — confirmed in server log asFailed to drain Session ... AI.Error.RateLimit.- missing auth for the
anthropicprovider (auth plugin failed to load withPluginModule.LoadError) — every Claude request failed the same way.
Additional Context
Server log (~/.local/share/opencode/log/opencode.log) for the rate-limit case — note the error message itself is the string Error:
level=ERROR message="Failed to drain Session"
cause="AI.Error: Error
at SessionStep.attempt ...
{
[cause]: AI.Error.RateLimit: Error
}"
For comparison, some provider errors do carry a real message and render fine, e.g.:
AI_APICallError: Claude Code 2.1.81 does not support this model; version 2.1.280 or newer is required
Code pointers (checkout at ~/Projects/opencode):
-
packages/tui/src/util/error.ts(errorFormat, line ~110): forErrorinstances renderserror.stack ??${error.name}: ${error.message}``; serialized session errors arrive as plain objects and fall through to the JSON path — either way the AI error'scausechain (which holds the real type, e.g. `RateLimit`) is never consulted, so both `name` and `message` render as the literal string `Error`. - The swallowing starts server-side: the
AI.Error*wrapper inpackages/coresession execution (Failed to drain Session,packages/core/src/session/execution/local.ts:25) already hasmessage: "Error"with the useful data only in[cause].
Suggested direction: when formatting a failed session error, unwrap cause (and/or include error.type/data) so the failure class and provider message reach the UI; alternatively, preserve the provider message when wrapping into AI.Error.* server-side.
Reproducible: consistently, whenever the provider request fails with an error whose message doesn't survive the AI.Error wrapping (observed on 2026-10-05/06, opencode 2.0.22).
Activity
github-actions commentedon Oct 6, 2026
This issue might be a duplicate of existing issues. Please check:
opencode-agent commentedon Oct 6, 2026
Thanks for the detailed report. I reproduced this on v2.0.22.
Steps:
Error, as in your log. I used anauthentication_error, since it isn't retried.Error: Error.With a descriptive provider message (for example
Incorrect API key provided), the TUI shows that text, but it never shows the failure class (Authentication,RateLimit, …). So when the provider's own message is generic, as with the Anthropic 429 you hit, the real cause is hidden. I couldn't test against a real Anthropic rate limit, but the behavior matches what you described.