Merge pull request #2484 from code-yeongyu/fix/issue-2393-cubic-error-name

fix: add FreeUsageLimitError to RETRYABLE_ERROR_NAMES set
This commit is contained in:
YeonGyu-Kim
2026-03-12 11:24:37 +09:00
committed by GitHub
2 changed files with 40 additions and 16 deletions
+22
View File
@@ -82,4 +82,26 @@ describe("model-error-classifier", () => {
//#then //#then
expect(provider).toBe("provider-x") expect(provider).toBe("provider-x")
}) })
test("treats FreeUsageLimitError (PascalCase name) as retryable by name", () => {
//#given
const error = { name: "FreeUsageLimitError" }
//#when
const result = shouldRetryError(error)
//#then
expect(result).toBe(true)
})
test("treats freeusagelimiterror (lowercase name) as retryable by name", () => {
//#given
const error = { name: "freeusagelimiterror" }
//#when
const result = shouldRetryError(error)
//#then
expect(result).toBe(true)
})
}) })
+18 -16
View File
@@ -6,13 +6,14 @@ import { readConnectedProvidersCache } from "./connected-providers-cache"
* These errors completely halt the action loop and should trigger fallback retry. * These errors completely halt the action loop and should trigger fallback retry.
*/ */
const RETRYABLE_ERROR_NAMES = new Set([ const RETRYABLE_ERROR_NAMES = new Set([
"ProviderModelNotFoundError", "providermodelnotfounderror",
"RateLimitError", "ratelimiterror",
"QuotaExceededError", "quotaexceedederror",
"InsufficientCreditsError", "insufficientcreditserror",
"ModelUnavailableError", "modelunavailableerror",
"ProviderConnectionError", "providerconnectionerror",
"AuthenticationError", "authenticationerror",
"freeusagelimiterror",
]) ])
/** /**
@@ -20,13 +21,13 @@ const RETRYABLE_ERROR_NAMES = new Set([
* These errors are typically user-induced or fixable without switching models. * These errors are typically user-induced or fixable without switching models.
*/ */
const NON_RETRYABLE_ERROR_NAMES = new Set([ const NON_RETRYABLE_ERROR_NAMES = new Set([
"MessageAbortedError", "messageabortederror",
"PermissionDeniedError", "permissiondeniederror",
"ContextLengthError", "contextlengtherror",
"TimeoutError", "timeouterror",
"ValidationError", "validationerror",
"SyntaxError", "syntaxerror",
"UserError", "usererror",
]) ])
/** /**
@@ -97,12 +98,13 @@ export interface ErrorInfo {
export function isRetryableModelError(error: ErrorInfo): boolean { export function isRetryableModelError(error: ErrorInfo): boolean {
// If we have an error name, check against known lists // If we have an error name, check against known lists
if (error.name) { if (error.name) {
const errorNameLower = error.name.toLowerCase()
// Explicit non-retryable takes precedence // Explicit non-retryable takes precedence
if (NON_RETRYABLE_ERROR_NAMES.has(error.name)) { if (NON_RETRYABLE_ERROR_NAMES.has(errorNameLower)) {
return false return false
} }
// Check if it's a known retryable error // Check if it's a known retryable error
if (RETRYABLE_ERROR_NAMES.has(error.name)) { if (RETRYABLE_ERROR_NAMES.has(errorNameLower)) {
return true return true
} }
} }