From dfe2ac43da7d70d63008cf242a18c59326a7f197 Mon Sep 17 00:00:00 2001 From: paramorph Date: Mon, 23 Jun 2025 22:26:28 +0300 Subject: [PATCH] Return error when structured output is truncated due to max_tokens limit --- responses/response.go | 8 ++++++++ responses/response_test.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/responses/response.go b/responses/response.go index 59735b97..3823ae15 100644 --- a/responses/response.go +++ b/responses/response.go @@ -59,6 +59,14 @@ func (r *ResponseService) New(ctx context.Context, body ResponseNewParams, opts opts = append(r.Options[:], opts...) path := "responses" err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...) + if err != nil { + return nil, err + } + + if res != nil && res.IncompleteDetails.Reason == "max_tokens" { + return nil, fmt.Errorf("structured output was truncated due to max_tokens limit (IncompleteDetails.Reason = 'max_tokens')") + } + return } diff --git a/responses/response_test.go b/responses/response_test.go index 6bddfe02..4658c131 100644 --- a/responses/response_test.go +++ b/responses/response_test.go @@ -6,6 +6,7 @@ import ( "context" "errors" "os" + "strings" "testing" "github.com/openai/openai-go" @@ -161,3 +162,35 @@ func TestResponseCancel(t *testing.T) { t.Fatalf("err should be nil: %s", err.Error()) } } + +func TestResponseTruncatedByMaxTokens(t *testing.T) { + baseURL := "http://localhost:4010" + if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { + baseURL = envURL + } + if !testutil.CheckTestServer(t, baseURL) { + return + } + client := openai.NewClient( + option.WithBaseURL(baseURL), + option.WithAPIKey("My API Key"), + ) + + _, err := client.Responses.New(context.TODO(), responses.ResponseNewParams{ + Model: shared.ResponsesModel("gpt-4o"), + Input: responses.ResponseNewParamsInputUnion{OfString: openai.String("Tell me a long story about a dragon")}, + Instructions: openai.String("Return a JSON with full story"), + MaxOutputTokens: openai.Int(5), + Temperature: openai.Float(1), + Text: responses.ResponseTextConfigParam{Format: responses.ResponseFormatTextConfigUnionParam{OfText: &shared.ResponseFormatTextParam{}}}, + ParallelToolCalls: openai.Bool(false), + }) + + if err == nil { + t.Fatal("Expected error due to max_tokens truncation, but got nil") + } + if !strings.Contains(err.Error(), "truncated") { + t.Fatalf("Expected truncation-related error, got: %v", err) + } + +}