fix(runtime-fallback): detect prettified quota errors without HTTP status codes (fixes #2747)

This commit is contained in:
MoerAI
2026-03-23 10:34:22 +09:00
parent 30dc50d880
commit 62d2704009
3 changed files with 102 additions and 1 deletions
@@ -166,3 +166,76 @@ describe("extractStatusCode", () => {
expect(extractStatusCode(error)).toBe(400)
})
})
describe("quota error detection (fixes #2747)", () => {
test("classifies prettified subscription quota error as quota_exceeded", () => {
//#given
const error = {
name: "AI_APICallError",
message: "Subscription quota exceeded. You can continue using free models.",
}
//#when
const errorType = classifyErrorType(error)
const retryable = isRetryableError(error, [402, 429, 500, 502, 503, 504])
//#then
expect(errorType).toBe("quota_exceeded")
expect(retryable).toBe(true)
})
test("classifies billing hard limit error as quota_exceeded", () => {
//#given
const error = { message: "You have reached your billing hard limit." }
//#when
const errorType = classifyErrorType(error)
//#then
expect(errorType).toBe("quota_exceeded")
})
test("classifies exhausted capacity error as quota_exceeded", () => {
//#given
const error = { message: "You have exhausted your capacity on this model." }
//#when
const errorType = classifyErrorType(error)
//#then
expect(errorType).toBe("quota_exceeded")
})
test("classifies out of credits error as quota_exceeded", () => {
//#given
const error = { message: "Out of credits. Please add more credits to continue." }
//#when
const errorType = classifyErrorType(error)
//#then
expect(errorType).toBe("quota_exceeded")
})
test("treats HTTP 402 Payment Required as retryable", () => {
//#given
const error = { statusCode: 402, message: "Payment Required" }
//#when
const retryable = isRetryableError(error, [402, 429, 500, 502, 503, 504])
//#then
expect(retryable).toBe(true)
})
test("matches subscription quota pattern in RETRYABLE_ERROR_PATTERNS", () => {
//#given
const error = { message: "Subscription quota exceeded. You can continue using free models." }
//#when
const retryable = isRetryableError(error, [429, 503])
//#then
expect(retryable).toBe(true)
})
})