diff --git a/CHANGELOG.md b/CHANGELOG.md index 85acbf7857..4be3ab58a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Docs: https://docs.openclaw.ai ### Fixes +- Model failover: treat HTTP 400 errors as failover-eligible, enabling automatic model fallback when providers return bad request errors. (#1879) Thanks @orenyomtov. - Exec approvals: format forwarded command text as inline/fenced monospace for safer approval scanning across channels. (#11937) - Config: clamp `maxTokens` to `contextWindow` to prevent invalid model configs. (#5516) Thanks @lailoo. - Docs: fix language switcher ordering and Japanese locale flag in Mintlify nav. (#12023) Thanks @joshp123. diff --git a/src/agents/failover-error.test.ts b/src/agents/failover-error.test.ts index a43ae289fd..d81781a905 100644 --- a/src/agents/failover-error.test.ts +++ b/src/agents/failover-error.test.ts @@ -11,6 +11,7 @@ describe("failover-error", () => { expect(resolveFailoverReasonFromError({ statusCode: "429" })).toBe("rate_limit"); expect(resolveFailoverReasonFromError({ status: 403 })).toBe("auth"); expect(resolveFailoverReasonFromError({ status: 408 })).toBe("timeout"); + expect(resolveFailoverReasonFromError({ status: 400 })).toBe("format"); }); it("infers format errors from error messages", () => { diff --git a/src/agents/failover-error.ts b/src/agents/failover-error.ts index 3a100c324d..ddef897176 100644 --- a/src/agents/failover-error.ts +++ b/src/agents/failover-error.ts @@ -160,6 +160,9 @@ export function resolveFailoverReasonFromError(err: unknown): FailoverReason | n if (status === 408) { return "timeout"; } + if (status === 400) { + return "format"; + } const code = (getErrorCode(err) ?? "").toUpperCase(); if (["ETIMEDOUT", "ESOCKETTIMEDOUT", "ECONNRESET", "ECONNABORTED"].includes(code)) {