fix(ai): keep known throttles out of overflow matching (#58866)

This commit is contained in:
Aiden Cline
2026-10-24 23:12:18 -05:00
committed by GitHub
Unverified
parent d7e56bc25e
commit 16cd50db22
2 changed files with 33 additions and 2 deletions
+1 -1
View File
@@ -262,7 +262,7 @@ export function classifyProviderFailure(input: ProviderFailure): AIError["reason
(codes.includes("context_length_exceeded") ||
codes.includes("model_context_window_exceeded") ||
codes.includes("request_too_large") ||
isContextOverflow(text))
(!codes.includes("throttlingexception") && isContextOverflow(text)))
)
return new InvalidRequestError({ ...details, classification: "context-overflow" })
if (input.status === 413 || isPayloadTooLarge(text))
+32 -1
View File
@@ -1,6 +1,6 @@
import { describe, expect, test } from "bun:test"
import { isContextOverflow, isContextOverflowFailure, isRetryable } from "../src/effect.js"
import { AIError } from "../src/schema/index.js"
import { AIError, HttpContext } from "../src/schema/index.js"
import { classifyProviderFailure, providerErrorMessage } from "../src/provider-error.js"
describe("provider error classification", () => {
@@ -449,6 +449,37 @@ describe("provider error classification", () => {
expect(isContextOverflow("Too many tokens")).toBe(true)
})
test("does not infer context overflow from known throttling exceptions", () => {
const cases = [
{ status: 429, data: { code: "ThrottlingException" } },
{ status: 429, rawBody: '{"__type":"com.amazonaws.bedrock#ThrottlingException"}' },
{ rawBody: '{"exception":{"type":"throttlingException"}}' },
{
status: 429,
http: new HttpContext({
url: "https://bedrock.test/model/example/converse-stream",
status: 429,
headers: { "x-amzn-errortype": "ThrottlingException:http://internal.amazon.com/coral/" },
}),
},
]
for (const input of cases) {
for (const message of ["Token limit exceeded", "Too many tokens, please try again later"]) {
const error = new AIError({ reason: classifyProviderFailure({ ...input, message }) })
expect(error.reason._tag).toBe("RateLimit")
expect(isContextOverflowFailure(error)).toBe(false)
expect(isRetryable(error)).toBe(true)
}
}
expect(
classifyProviderFailure({
message: "prompt is too long",
status: 400,
data: { code: "ValidationException" },
}),
).toMatchObject({ _tag: "InvalidRequest", classification: "context-overflow" })
})
test("does not let substituted server codes make a 4xx retryable", () => {
const openai = { error: { type: "server_error", message: "Upstream request failed: Model is unavailable." } }
const anthropic = {