Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions internal/apischema/openai/openai.go
Original file line number Diff line number Diff line change
Expand Up @@ -1662,6 +1662,47 @@ type ErrorType struct {
EventID *string `json:"event_id,omitempty"`
}

// UnmarshalJSON allows OpenAI-compatible backends to provide `error.code` as either a JSON string or number.
func (e *ErrorType) UnmarshalJSON(data []byte) error {
type errorTypeAlias ErrorType
aux := struct {
errorTypeAlias
Code json.RawMessage `json:"code,omitempty"`
}{}

if err := json.Unmarshal(data, &aux); err != nil {
return err
}

*e = ErrorType(aux.errorTypeAlias)
if len(aux.Code) == 0 || string(aux.Code) == "null" {
e.Code = nil
return nil
}

var code string
if err := json.Unmarshal(aux.Code, &code); err == nil {
e.Code = &code
return nil
}

var codeInt int64
if err := json.Unmarshal(aux.Code, &codeInt); err == nil {
code = strconv.FormatInt(codeInt, 10)
e.Code = &code
return nil
}

var codeFloat float64
if err := json.Unmarshal(aux.Code, &codeFloat); err == nil {
code = strconv.FormatFloat(codeFloat, 'f', -1, 64)
e.Code = &code
return nil
}

return fmt.Errorf("error.code must be string or number")
}

// ModelList is described in the OpenAI API documentation
// https://platform.openai.com/docs/api-reference/models/list
type ModelList struct {
Expand Down
7 changes: 7 additions & 0 deletions internal/translator/anthropic_openai_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,13 @@ func TestAnthropicToOpenAITranslator_ResponseError(t *testing.T) {
wantErrType: "invalid_request_error",
wantErrMsg: "Bad request",
},
{
name: "JSON error with numeric code from OpenAI-compatible backend",
headers: map[string]string{contentTypeHeaderName: "application/json"},
body: `{"type":"error","error":{"type":"invalid_request_error","message":"Bad request","param":null,"code":400}}`,
wantErrType: "invalid_request_error",
wantErrMsg: "Bad request",
},
{
name: "non-JSON 400 error",
headers: map[string]string{statusHeaderName: "400", contentTypeHeaderName: "text/plain"},
Expand Down