fix: narrow api_error detection to exclude billing/auth patterns
This commit is contained in:
parent
876566439e
commit
04755c2327
@ -860,4 +860,35 @@ describe("classifyFailoverReason", () => {
|
||||
),
|
||||
).toBe("timeout");
|
||||
});
|
||||
it("does not shadow billing errors that carry api_error type", () => {
|
||||
// A provider may wrap a billing error in a JSON payload with "type":"api_error".
|
||||
// The billing classifier must win over the broad api_error transient match.
|
||||
expect(
|
||||
classifyFailoverReason(
|
||||
'{"type":"error","error":{"type":"api_error","message":"insufficient credits"}}',
|
||||
),
|
||||
).toBe("billing");
|
||||
expect(
|
||||
classifyFailoverReason(
|
||||
'{"type":"error","error":{"type":"api_error","message":"Payment required"}}',
|
||||
),
|
||||
).toBe("billing");
|
||||
});
|
||||
it("does not shadow auth errors that carry api_error type", () => {
|
||||
expect(
|
||||
classifyFailoverReason(
|
||||
'{"type":"error","error":{"type":"api_error","message":"invalid api key"}}',
|
||||
),
|
||||
).toBe("auth");
|
||||
expect(
|
||||
classifyFailoverReason(
|
||||
'{"type":"error","error":{"type":"api_error","message":"unauthorized"}}',
|
||||
),
|
||||
).toBe("auth");
|
||||
expect(
|
||||
classifyFailoverReason(
|
||||
'{"type":"error","error":{"type":"api_error","message":"permission_error"}}',
|
||||
),
|
||||
).toBe("auth_permanent");
|
||||
});
|
||||
});
|
||||
|
||||
@ -857,8 +857,15 @@ function isJsonApiInternalServerError(raw: string): boolean {
|
||||
// {"type":"error","error":{"type":"api_error","message":"Internal server error"}}
|
||||
// Non-standard providers (e.g. MiniMax) may use different message text:
|
||||
// {"type":"api_error","message":"unknown error, 520 (1000)"}
|
||||
// Any api_error type indicates a provider-side failure regardless of message text.
|
||||
return value.includes('"type":"api_error"');
|
||||
if (!value.includes('"type":"api_error"')) {
|
||||
return false;
|
||||
}
|
||||
// Billing and auth errors can also carry "type":"api_error". Exclude them so
|
||||
// the more specific classifiers further down the chain handle them correctly.
|
||||
if (isBillingErrorMessage(raw) || isAuthErrorMessage(raw) || isAuthPermanentErrorMessage(raw)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function parseImageDimensionError(raw: string): {
|
||||
@ -1011,24 +1018,27 @@ export function classifyFailoverReason(raw: string): FailoverReason | null {
|
||||
// Treat remaining transient 5xx provider failures as retryable transport issues.
|
||||
return "timeout";
|
||||
}
|
||||
if (isJsonApiInternalServerError(raw)) {
|
||||
return "timeout";
|
||||
}
|
||||
if (isCloudCodeAssistFormatError(raw)) {
|
||||
return "format";
|
||||
}
|
||||
// Billing and auth classifiers run before the broad isJsonApiInternalServerError
|
||||
// check so that provider errors like {"type":"api_error","message":"insufficient
|
||||
// balance"} are correctly classified as "billing"/"auth" rather than "timeout".
|
||||
if (isBillingErrorMessage(raw)) {
|
||||
return "billing";
|
||||
}
|
||||
if (isTimeoutErrorMessage(raw)) {
|
||||
return "timeout";
|
||||
}
|
||||
if (isAuthPermanentErrorMessage(raw)) {
|
||||
return "auth_permanent";
|
||||
}
|
||||
if (isAuthErrorMessage(raw)) {
|
||||
return "auth";
|
||||
}
|
||||
if (isJsonApiInternalServerError(raw)) {
|
||||
return "timeout";
|
||||
}
|
||||
if (isCloudCodeAssistFormatError(raw)) {
|
||||
return "format";
|
||||
}
|
||||
if (isTimeoutErrorMessage(raw)) {
|
||||
return "timeout";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user