Skip to content

Commit 3756ff6

Browse files
Copilotnacx
authored andcommitted
translator: handle numeric OpenAI error.code in Anthropic→OpenAI error translation (envoyproxy#2161)
**Description** Anthropic→OpenAI error translation could fail with an internal 500 when an OpenAI-compatible upstream returned a structured JSON error where `error.code` was numeric (e.g. `400`) instead of string. This change makes the error model tolerant to both representations so upstream 4xx diagnostics can still be translated and surfaced to Anthropic clients. - **Schema decoding hardening (`internal/apischema/openai/openai.go`)** - Added `UnmarshalJSON` for `openai.ErrorType`. - `error.code` now accepts: - JSON string (`"code":"400"`) - JSON number (`"code":400`) - `null` / omitted - Numeric values are normalized to the existing internal `*string` field. - **Translator regression coverage (`internal/translator/anthropic_openai_test.go`)** - Extended `TestAnthropicToOpenAITranslator_ResponseError` with a JSON error fixture containing numeric `code`. - Confirms response still maps to Anthropic error envelope with expected `type` and `message`. ```json { "type": "error", "error": { "type": "invalid_request_error", "message": "Bad request", "param": null, "code": 400 } } ``` **Related Issues/PRs (if applicable)** Fixes envoyproxy#2151 **Special notes for reviewers (if applicable)** N/A --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Ignasi Barrera <ignasi@tetrate.io> Signed-off-by: yxia216 <yxia216@bloomberg.net>
1 parent 8299d9a commit 3756ff6

2 files changed

Lines changed: 48 additions & 0 deletions

File tree

internal/apischema/openai/openai.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1662,6 +1662,47 @@ type ErrorType struct {
16621662
EventID *string `json:"event_id,omitempty"`
16631663
}
16641664

1665+
// UnmarshalJSON allows OpenAI-compatible backends to provide `error.code` as either a JSON string or number.
1666+
func (e *ErrorType) UnmarshalJSON(data []byte) error {
1667+
type errorTypeAlias ErrorType
1668+
aux := struct {
1669+
errorTypeAlias
1670+
Code json.RawMessage `json:"code,omitempty"`
1671+
}{}
1672+
1673+
if err := json.Unmarshal(data, &aux); err != nil {
1674+
return err
1675+
}
1676+
1677+
*e = ErrorType(aux.errorTypeAlias)
1678+
if len(aux.Code) == 0 || string(aux.Code) == "null" {
1679+
e.Code = nil
1680+
return nil
1681+
}
1682+
1683+
var code string
1684+
if err := json.Unmarshal(aux.Code, &code); err == nil {
1685+
e.Code = &code
1686+
return nil
1687+
}
1688+
1689+
var codeInt int64
1690+
if err := json.Unmarshal(aux.Code, &codeInt); err == nil {
1691+
code = strconv.FormatInt(codeInt, 10)
1692+
e.Code = &code
1693+
return nil
1694+
}
1695+
1696+
var codeFloat float64
1697+
if err := json.Unmarshal(aux.Code, &codeFloat); err == nil {
1698+
code = strconv.FormatFloat(codeFloat, 'f', -1, 64)
1699+
e.Code = &code
1700+
return nil
1701+
}
1702+
1703+
return fmt.Errorf("error.code must be string or number")
1704+
}
1705+
16651706
// ModelList is described in the OpenAI API documentation
16661707
// https://platform.openai.com/docs/api-reference/models/list
16671708
type ModelList struct {

internal/translator/anthropic_openai_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,13 @@ func TestAnthropicToOpenAITranslator_ResponseError(t *testing.T) {
430430
wantErrType: "invalid_request_error",
431431
wantErrMsg: "Bad request",
432432
},
433+
{
434+
name: "JSON error with numeric code from OpenAI-compatible backend",
435+
headers: map[string]string{contentTypeHeaderName: "application/json"},
436+
body: `{"type":"error","error":{"type":"invalid_request_error","message":"Bad request","param":null,"code":400}}`,
437+
wantErrType: "invalid_request_error",
438+
wantErrMsg: "Bad request",
439+
},
433440
{
434441
name: "non-JSON 400 error",
435442
headers: map[string]string{statusHeaderName: "400", contentTypeHeaderName: "text/plain"},

0 commit comments

Comments
 (0)