fix: preserve structured 5xx server errors

This commit is contained in:
Altay
2026-05-09 19:40:00 +03:00
parent b721ec8be9
commit db94785e05
4 changed files with 24 additions and 6 deletions

View File

@@ -4,16 +4,11 @@ Docs: https://docs.openclaw.ai
## Unreleased
### Fixes
- Cron/failover: classify structured OpenAI-compatible `server_error` payloads as `server_error`, expose that reason in cron state, and let one-shot cron retry policy honor `retryOn: ["server_error"]` without requiring raw `5xx` text. (#45594) Thanks @clovericbot.
## 2026.5.8
### Changes
### Fixes
- Cron/failover: classify structured OpenAI-compatible `server_error` payloads as `server_error`, expose that reason in cron state, and let one-shot cron retry policy honor `retryOn: ["server_error"]` without requiring raw `5xx` text. (#45594) Thanks @clovericbot.
- Feishu: auto-thread `message(action="send")` replies inside the topic when the active session is group_topic or group_topic_sender, and propagate `replyInThread` through text, card, and media outbound adapters so topic-scoped sessions no longer post at the group root. Fixes #74903. (#77151) Thanks @ai-hpc.
- WhatsApp: pass routing context into voice-note transcript echo preflight so echoed transcripts can deliver to the originating chat. Fixes #79778. (#79788) Thanks @hclsys.

View File

@@ -986,9 +986,16 @@ describe("failover-error", () => {
message: OPENAI_SERVER_ERROR_PAYLOAD,
}),
).toBe("server_error");
expect(
resolveFailoverReasonFromError({
status: 500,
message: OPENAI_SERVER_ERROR_PAYLOAD,
}),
).toBe("server_error");
const err = coerceToFailoverError(
{
status: 500,
message: OPENAI_SERVER_ERROR_PAYLOAD,
},
{ provider: "openai-codex", model: "gpt-5.4" },

View File

@@ -683,6 +683,19 @@ describe("classifyFailoverReasonFromHttpStatus", () => {
expect(classifyFailoverReasonFromHttpStatus(422, payload)).toBe("format");
});
it("preserves structured server_error markers on explicit HTTP 5xx statuses", () => {
expect(classifyFailoverReasonFromHttpStatus(500, OPENAI_SERVER_ERROR_PAYLOAD)).toBe(
"server_error",
);
expect(classifyFailoverReasonFromHttpStatus(502, OPENAI_SERVER_ERROR_PAYLOAD)).toBe(
"server_error",
);
expect(classifyFailoverReasonFromHttpStatus(504, OPENAI_SERVER_ERROR_PAYLOAD)).toBe(
"server_error",
);
expect(classifyFailoverReasonFromHttpStatus(500)).toBe("timeout");
});
it("treats generic HTTP 410 responses as retryable timeouts", () => {
expect(classifyFailoverReasonFromHttpStatus(410)).toBe("timeout");
expect(classifyFailoverReasonFromHttpStatus(410, "")).toBe("timeout");

View File

@@ -697,6 +697,9 @@ function classifyFailoverClassificationFromHttpStatus(
return toReasonClassification("timeout");
}
if (status === 500 || status === 502 || status === 504) {
if (messageReason === "server_error") {
return messageClassification;
}
return toReasonClassification("timeout");
}
if (status === 529) {