Repository navigation
fix(claude-code): classify invalid_request instead of a dead-end error - #195
Merged
akemmanuel merged 2 commits intoNov 12, 2026
Conversation
The Claude Agent SDK surfaces a model rejection as a bare
SDKAssistantMessageError code (e.g. `invalid_request`, `model_not_found`).
A ClaudeCodeError carries no numeric status, so these fell through
`assistantErrorMessage`'s switch and `normalizeModelError` had no text rule
to catch them — users saw the opaque "Model provider request failed /
unknown" with no hint and no way to act.
- assistantErrorMessage: cover every SDK error code, with actionable text
for invalid_request (oversized request or a referenced attachment that can
no longer be read) and model_not_found, plus the account/verification/
cloud-credential auth codes.
- normalizeModelError: classify plainly-worded bad requests ("invalid
request" / "model not found") as `invalid_request` even without a numeric
status, so Claude Code's text-only errors reach the right bucket.
- Tests for both paths.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
akemmanuel
merged commit Nov 12, 2026
b06fce8
into
akemmanuel:t3/claude-code-provider
2 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A Claude Code run can fail with a completely opaque message:
invalid_requestis one of the Claude Agent SDK'sSDKAssistantMessageErrorcodes (Anthropic HTTP 400). The SDK hands us only the bare code — no detail.
On OpenGUI's side two gaps turned it into a dead end:
assistantErrorMessagehad no case forinvalid_request(normodel_not_found,account_on_hold,verification_required,cloud_credential_error), so it fell through to the generic wording.ClaudeCodeErrorcarries no numericstatus, andnormalizeModelErrorhad no text rule for a plainly-worded bad request — so it landed in
unknown/"Model provider request failed", withretryable: falseandnothing actionable for the user.
Real-world trigger that surfaced this: a long session kept re-sending image
attachments whose files had disappeared from
/tmp, so every subsequent turngot a 400 and the session was permanently wedged behind a meaningless error.
Change
protocol.ts—assistantErrorMessage: cover every SDK error code.invalid_requestnow explains the likely causes (request too large, or areferenced attachment that can no longer be read) and suggests starting a
new session / removing missing attachments;
model_not_foundis wordedclearly; the account/verification/cloud-credential codes map to auth.
transport.ts—normalizeModelError: classify plainly-worded badrequests (
invalid request/model not found) asinvalid_requestevenwithout a numeric status, so Claude Code's text-only errors reach the right
bucket. Narrow, additive regex; benefits any provider that words a 400 in
text.
errorMessagetext path and the newassistantErrorMessagecode path.Testing
Follow-up (not in this PR)
The deeper robustness gap — the provider boundary should degrade a
no-longer-readable image reference to a placeholder instead of sending a
broken block — is worth a separate change so a vanished
/tmpfile can'tpermanently wedge a session.