mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-28 05:16:23 -06:00
fix(cron): require HTTP context for server_error retries
Narrow cron server_error retry classification so incidental 500-599 numbers in failure text no longer trigger retryable server_error. Genuine HTTP/status 5xx strings, canonical 5xx phrases, 5xx, and standalone terse codes still retry.
Maintainer proof: focused cron retry tests, formatter/lint/diff checks, clean autoreview, Testbox-through-Crabbox check:changed tbx_01kteteqqrppbzgh560sybe0nk / Actions run 27066938422, and green PR CI on 6124f14850.
Fixes #90947.
This commit is contained in:
@@ -36,4 +36,38 @@ describe("resolveCronExecutionRetryHint", () => {
|
||||
retryable: false,
|
||||
});
|
||||
});
|
||||
|
||||
it("does not classify bare 5xx-looking numbers as server_error", () => {
|
||||
for (const message of [
|
||||
"context limit 512 exceeded",
|
||||
"process exited with 503 lines of output",
|
||||
"ENOENT: no such file '/var/run/app-540.sock'",
|
||||
"killed worker pid 511 after deadline",
|
||||
"assertion failed: expected 500 got 0",
|
||||
"error 500 got 0",
|
||||
"process exited with code 500",
|
||||
]) {
|
||||
expect(resolveCronExecutionRetryHint(message, ["server_error"])).toEqual({
|
||||
retryable: false,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it("classifies genuine HTTP 5xx errors as server_error", () => {
|
||||
for (const message of [
|
||||
"HTTP 503 Service Unavailable",
|
||||
"received status 500 from upstream",
|
||||
"500 Internal Server Error",
|
||||
"502 Bad Gateway",
|
||||
"upstream returned 5xx",
|
||||
"response code: 502",
|
||||
"503",
|
||||
"500",
|
||||
]) {
|
||||
expect(resolveCronExecutionRetryHint(message, ["server_error"])).toEqual({
|
||||
retryable: true,
|
||||
category: "server_error",
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
+12
-1
@@ -7,6 +7,17 @@ export type CronRetryHint = {
|
||||
category?: CronRetryOn;
|
||||
};
|
||||
|
||||
// A bare 5xx-looking number embedded in prose is not an HTTP server error: cron
|
||||
// failure messages routinely contain such numbers ("context limit 512 exceeded",
|
||||
// "exited with 503 lines", "pid 511 killed", a "...-540.sock" path), and
|
||||
// /\b5\d{2}\b/ matched all of them, wrongly marking permanent failures retryable.
|
||||
// Match a 5xx number only with HTTP/status context, a canonical 5xx phrase, or
|
||||
// when it is the entire message (a terse "503"), so genuine
|
||||
// "500 Internal Server Error" / "502 Bad Gateway" / "5xx" still classify while
|
||||
// incidental numbers in longer messages do not.
|
||||
const SERVER_ERROR_PATTERN =
|
||||
/\b(?:https?|status(?:[ _]code)?|response(?:[ _]code)?|http(?:[ _]status)?)\b[\s:=#"']{0,4}5\d{2}\b|\b5\d{2}\b[\s:)\].,-]*(?:internal server error|server error|bad gateway|service unavailable|gateway time-?out)\b|\binternal server error\b|\bbad gateway\b|\bservice unavailable\b|\bgateway time-?out\b|\b5xx\b|^\s*5\d{2}\s*$/i;
|
||||
|
||||
const TRANSIENT_PATTERNS: Record<CronRetryOn, RegExp> = {
|
||||
rate_limit:
|
||||
/(rate[_ ]limit|too many requests|429|resource has been exhausted|cloudflare|tokens per day)/i,
|
||||
@@ -15,7 +26,7 @@ const TRANSIENT_PATTERNS: Record<CronRetryOn, RegExp> = {
|
||||
network:
|
||||
/(network|fetch failed|socket|econnreset|econnrefused|eai_again|enetdown|ehostunreach|ehostdown|enetreset|enetunreach|epipe)/i,
|
||||
timeout: /(timeout|etimedout)/i,
|
||||
server_error: /\b5\d{2}\b/,
|
||||
server_error: SERVER_ERROR_PATTERN,
|
||||
};
|
||||
|
||||
/** Classifies cron execution errors against the configured retryable transient categories. */
|
||||
|
||||
Reference in New Issue
Block a user