fix(failover): improve internal server error classification (#73844)

* fix(failover): improve internal server error classification

* fix: cover bare internal server status

---------

Co-authored-by: Altay <altay@uinaf.dev>
This commit is contained in:
Gabriel
2026-05-02 05:35:55 -04:00
committed by GitHub
parent 6de92d0bd4
commit 3ea2d2a928
3 changed files with 16 additions and 1 deletions

View File

@@ -213,6 +213,7 @@ Docs: https://docs.openclaw.ai
- Gateway/config: log config health-state write failures instead of silently hiding config observe-recovery write errors. Thanks @sallyom.
- Diagnostics: reset stuck-session timers on reply, tool, status, block, and ACP progress events, and back off repeated `session.stuck` diagnostics while a session remains unchanged. Supersedes #72010. Thanks @rubencu.
- Gateway/agents: avoid rebuilding core tools for plugin-only allowlists and keep the full plugin registry cache warm across scoped plugin loads, reducing per-turn latency spikes. Fixes #75882, #75907, #75906, #75887, and #75851. (#75922) Thanks @obviyus.
- Agents/failover: classify bare `status: internal server error` provider messages as retryable server errors so model fallback can rotate instead of stopping. (#73844) Thanks @thesomewhatyou.
## 2026.4.30

View File

@@ -4,6 +4,7 @@ import {
isBillingErrorMessage,
isOverloadedErrorMessage,
isRateLimitErrorMessage,
isServerErrorMessage,
} from "./failover-matches.js";
describe("Z.ai vendor error codes (#48988)", () => {
@@ -92,3 +93,13 @@ describe("Z.ai vendor error codes (#48988)", () => {
});
});
});
describe("server error status classification", () => {
it("classifies a bare internal server error status as server error", () => {
expect(isServerErrorMessage("status: internal server error")).toBe(true);
});
it("does not classify prefixed plain internal server error status prose", () => {
expect(isServerErrorMessage("Proxy notice: Status: Internal Server Error")).toBe(false);
});
});

View File

@@ -309,5 +309,8 @@ export function isServerErrorMessage(raw: string): boolean {
return true;
}
const scrubbed = value.replace(STATUS_INTERNAL_SERVER_ERROR_RE, "").trim();
return scrubbed.length > 0 && matchesErrorPatterns(scrubbed, ERROR_PATTERNS.serverError);
if (scrubbed === "") {
return true;
}
return matchesErrorPatterns(scrubbed, ERROR_PATTERNS.serverError);
}