fix(auth): classify permission_error as auth_permanent for profile fallback (#31324)
When an OAuth auth profile returns HTTP 403 with permission_error (e.g. expired plan), the error was not matched by the authPermanent patterns. This caused the profile to receive only a short cooldown instead of being disabled, so the gateway kept retrying the same broken profile indefinitely. Add "permission_error" and "not allowed for this organization" to the authPermanent error patterns so these errors trigger the longer billing/auth_permanent disable window and proper profile rotation. Closes #31306 Made-with: Cursor Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
This commit is contained in:
parent
f2dbaf70fa
commit
40e078a567
@ -100,6 +100,32 @@ describe("failover-error", () => {
|
|||||||
expect(err?.provider).toBe("anthropic");
|
expect(err?.provider).toBe("anthropic");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("403 permission_error returns auth_permanent", () => {
|
||||||
|
expect(
|
||||||
|
resolveFailoverReasonFromError({
|
||||||
|
status: 403,
|
||||||
|
message:
|
||||||
|
"permission_error: OAuth authentication is currently not allowed for this organization.",
|
||||||
|
}),
|
||||||
|
).toBe("auth_permanent");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("permission_error in error message string classifies as auth_permanent", () => {
|
||||||
|
const err = coerceToFailoverError(
|
||||||
|
"HTTP 403 permission_error: OAuth authentication is currently not allowed for this organization.",
|
||||||
|
{ provider: "anthropic", model: "claude-opus-4-6" },
|
||||||
|
);
|
||||||
|
expect(err?.reason).toBe("auth_permanent");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("'not allowed for this organization' classifies as auth_permanent", () => {
|
||||||
|
const err = coerceToFailoverError(
|
||||||
|
"OAuth authentication is currently not allowed for this organization",
|
||||||
|
{ provider: "anthropic", model: "claude-opus-4-6" },
|
||||||
|
);
|
||||||
|
expect(err?.reason).toBe("auth_permanent");
|
||||||
|
});
|
||||||
|
|
||||||
it("describes non-Error values consistently", () => {
|
it("describes non-Error values consistently", () => {
|
||||||
const described = describeFailoverError(123);
|
const described = describeFailoverError(123);
|
||||||
expect(described.message).toBe("123");
|
expect(described.message).toBe("123");
|
||||||
|
|||||||
@ -660,6 +660,8 @@ const ERROR_PATTERNS = {
|
|||||||
"key has been revoked",
|
"key has been revoked",
|
||||||
"account has been deactivated",
|
"account has been deactivated",
|
||||||
/could not (?:authenticate|validate).*(?:api[_ ]?key|credentials)/i,
|
/could not (?:authenticate|validate).*(?:api[_ ]?key|credentials)/i,
|
||||||
|
"permission_error",
|
||||||
|
"not allowed for this organization",
|
||||||
],
|
],
|
||||||
auth: [
|
auth: [
|
||||||
/invalid[_ ]?api[_ ]?key/,
|
/invalid[_ ]?api[_ ]?key/,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user