fix(openai): stop truncating a provider error before it is parsed

statusError capped the body at 2 KiB and then unmarshalled, so any error longer
than that failed to parse and the caller received a raw JSON fragment cut
mid-object instead of the provider's message. Azure content-filter and
structured-output responses, which echo the schema, routinely exceed it.

The cap moves to 64 KiB: still bounded, but above the largest error body these
providers send. The existing cap test is written against the constant and keeps
holding.

PAGI-132
This commit is contained in:
Sergey Kozyrenko
2026-08-23 10:41:16 +07:00
parent 058e344d90
commit 28f73650cd
2 changed files with 22 additions and 1 deletions
@@ -60,7 +60,7 @@ type errorMessage struct {
} `json:"error"`
}
const maxErrorBodyBytes = 2048
const maxErrorBodyBytes = 64 << 10
func statusError(statusCode int, body io.Reader) error {
msg := fmt.Sprintf("API returned unexpected status code: %d", statusCode)
@@ -30,3 +30,24 @@ func TestStatusErrorCapsTheQuotedBody(t *testing.T) {
t.Fatalf("error grew to %d bytes, want it capped near %d", len(err.Error()), maxErrorBodyBytes)
}
}
func TestStatusErrorParsesABodyLargerThanTwoKilobytes(t *testing.T) {
padding := strings.Repeat("d", 8<<10)
body := `{"error":{"message":"content filter triggered","type":"invalid_request_error","detail":"` +
padding + `"}}`
err := statusError(400, strings.NewReader(body))
if err == nil {
t.Fatal("want an error")
}
got := err.Error()
if !strings.Contains(got, "content filter triggered") {
t.Errorf("provider message lost: %s", got)
}
if strings.Contains(got, `{"error"`) {
t.Errorf("body was quoted raw instead of parsed: %.120s", got)
}
if strings.Contains(got, padding[:64]) {
t.Errorf("padding leaked into the error: %.120s", got)
}
}