diff --git a/src/agents/failover-error.test.ts b/src/agents/failover-error.test.ts index 8b2cb846298..413e9da8c31 100644 --- a/src/agents/failover-error.test.ts +++ b/src/agents/failover-error.test.ts @@ -100,6 +100,32 @@ describe("failover-error", () => { 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", () => { const described = describeFailoverError(123); expect(described.message).toBe("123"); diff --git a/src/agents/pi-embedded-helpers/errors.ts b/src/agents/pi-embedded-helpers/errors.ts index 3d608696705..aa64450df6b 100644 --- a/src/agents/pi-embedded-helpers/errors.ts +++ b/src/agents/pi-embedded-helpers/errors.ts @@ -660,6 +660,8 @@ const ERROR_PATTERNS = { "key has been revoked", "account has been deactivated", /could not (?:authenticate|validate).*(?:api[_ ]?key|credentials)/i, + "permission_error", + "not allowed for this organization", ], auth: [ /invalid[_ ]?api[_ ]?key/,