Bug
When all provider bindings are exhausted on the Anthropic surface (/v1/messages), the buffered upstream error body is passed through OpenAIToAnthropicError to produce the final Anthropic-format error response. For Gemini errors this produces an empty type field.
Gemini's error format uses error.status for the error type:
{"error": {"code": 429, "message": "...", "status": "RESOURCE_EXHAUSTED"}}
OpenAI's format uses error.type:
{"error": {"type": "rate_limit_error", "message": "..."}}
OpenAIToAnthropicError reads error.type via gjson. On a Gemini error body, that path returns an empty string, so the client receives a well-formed Anthropic error with the correct message but an empty type field:
{"type": "error", "error": {"type": "", "message": "RESOURCE_EXHAUSTED"}}
Where
Wherever OpenAIToAnthropicError is called with a Gemini-format error body — specifically the exhausted-bindings path in the proxy layer that feeds the buffered upstream error through translation.
Suggested fix
A GeminiToAnthropicError helper that reads error.status and maps Gemini's status strings (RESOURCE_EXHAUSTED, INVALID_ARGUMENT, PERMISSION_DENIED, etc.) to Anthropic error types (rate_limit_error, invalid_request_error, authentication_error, etc.), used in place of OpenAIToAnthropicError when the upstream provider is Gemini.
Context
Flagged by @steventohme during review of PR #450
(fix/google-native-client-premature-writeheader). The buffering fix in that PR is what surfaces this — before it, Gemini errors were streamed
raw to the client rather than translated. Now that they're buffered and translated, the format mismatch is reachable.
Bug
When all provider bindings are exhausted on the Anthropic surface (
/v1/messages), the buffered upstream error body is passed throughOpenAIToAnthropicErrorto produce the final Anthropic-format error response. For Gemini errors this produces an emptytypefield.Gemini's error format uses
error.statusfor the error type:{"error": {"code": 429, "message": "...", "status": "RESOURCE_EXHAUSTED"}}OpenAI's format uses
error.type:{"error": {"type": "rate_limit_error", "message": "..."}}OpenAIToAnthropicErrorreadserror.typevia gjson. On a Gemini error body, that path returns an empty string, so the client receives a well-formed Anthropic error with the correct message but an emptytypefield:{"type": "error", "error": {"type": "", "message": "RESOURCE_EXHAUSTED"}}Where
Wherever
OpenAIToAnthropicErroris called with a Gemini-format error body — specifically the exhausted-bindings path in the proxy layer that feeds the buffered upstream error through translation.Suggested fix
A
GeminiToAnthropicErrorhelper that readserror.statusand maps Gemini's status strings (RESOURCE_EXHAUSTED,INVALID_ARGUMENT,PERMISSION_DENIED, etc.) to Anthropic error types (rate_limit_error,invalid_request_error,authentication_error, etc.), used in place ofOpenAIToAnthropicErrorwhen the upstream provider is Gemini.Context
Flagged by @steventohme during review of PR #450
(fix/google-native-client-premature-writeheader). The buffering fix in that PR is what surfaces this — before it, Gemini errors were streamed
raw to the client rather than translated. Now that they're buffered and translated, the format mismatch is reachable.