From 28f73650cd8d6c5101acbcd9fdd8b0fc22f4d0ea Mon Sep 17 00:00:00 2001 From: Sergey Kozyrenko Date: Sun, 23 Aug 2026 10:41:16 +0700 Subject: [PATCH] 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 --- .../internal/openaiclient/completions.go | 2 +- .../internal/openaiclient/statuserror_test.go | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/llms/openai/internal/openaiclient/completions.go b/llms/openai/internal/openaiclient/completions.go index 26537b5a..240a41f0 100644 --- a/llms/openai/internal/openaiclient/completions.go +++ b/llms/openai/internal/openaiclient/completions.go @@ -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) diff --git a/llms/openai/internal/openaiclient/statuserror_test.go b/llms/openai/internal/openaiclient/statuserror_test.go index 018ebd69..d5327b86 100644 --- a/llms/openai/internal/openaiclient/statuserror_test.go +++ b/llms/openai/internal/openaiclient/statuserror_test.go @@ -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) + } +}