fix(ai): classified dashscope throttles as rate limits

Prioritized rate-limit wording before auth wording in auth-gateway error classification so DashScope throttling messages that contain unauthorized do not invalidate credentials.

Fixes #3172
This commit is contained in:
roboomp
2026-06-21 05:24:06 +00:00
parent 4cf1ca517f
commit 801a0dd302
3 changed files with 16 additions and 4 deletions
+4
View File
@@ -2,6 +2,10 @@
## [Unreleased]
### Fixed
- Fixed DashScope 429 rate-limit messages that mention authorization being classified as credential failures, preventing valid API keys from being invalidated after throttling. ([#3172](https://github.com/can1357/oh-my-pi/issues/3172))
## [16.1.9] - 2026-06-21
### Added
+6 -4
View File
@@ -229,11 +229,10 @@ export function classifyGatewayError(err: unknown): { status: number; type: stri
if (/\baborted\b|\babort signal\b/i.test(message)) {
return { status: 499, type: "request_aborted", message };
}
if (/\b(?:unauthorized|forbidden)\b/i.test(message)) {
return { status: 401, type: "authentication_error", message };
}
if (
// Match rate-limit phrasings without colliding with
// Match rate-limit phrasings before auth wording: some providers
// describe throttling as "unauthorized due to rate limit".
// Keep boundaries so this does not collide with
// `GenerateContentRequest`, `accelerate`, `iterate`, `deprecated`, etc.
/\brate[- _]?limit(?:s|ed|ing)?\b|\bquota(?:_exceeded| exceeded)?\b|\btoo[- _]many[- _]requests\b/i.test(
message,
@@ -249,6 +248,9 @@ export function classifyGatewayError(err: unknown): { status: number; type: stri
) {
return { status: 429, type: "rate_limit_error", message };
}
if (/\b(?:unauthorized|forbidden)\b/i.test(message)) {
return { status: 401, type: "authentication_error", message };
}
if (/\b(?:unsupported|invalid_request|invalid request|bad request|malformed)\b/i.test(message)) {
return { status: 400, type: "invalid_request_error", message };
}
@@ -54,6 +54,12 @@ describe("auth-gateway classifyGatewayError", () => {
expect(c.type).toBe("rate_limit_error");
});
it("prefers rate-limit wording over auth wording", () => {
const c = classifyGatewayError(new Error("Rate limit exceeded - unauthorized due to throttling"));
expect(c.status).toBe(429);
expect(c.type).toBe("rate_limit_error");
});
it("classifies Codex 'You have hit your ChatGPT usage limit' as 429", () => {
// Verbatim shape Codex returns from the `usage_limit_reached` branch
// in `parseCodexError`. No embedded `HTTP NNN`/`(NNN)`/`status NNN`