mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 16:01:01 +00:00
fix(failover): classify finish_reason: network_error as timeout (#61281)
OpenAI-compatible providers (e.g. Z.AI) surface transport errors as `finish_reason: network_error` in the stream body. The existing `\breason:` pattern does not match `finish_reason:` because `_` is a word character, so no word boundary exists before `reason`. This causes the error to fall through unclassified and skip the timeout-failover path entirely. Add an explicit `\bfinish_reason:` pattern that covers the same set of terminal reasons already handled by the `\breason:` pattern.
This commit is contained in:
@@ -779,6 +779,17 @@ describe("isFailoverErrorMessage", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("matches Provider finish_reason: network_error as timeout (#61281)", () => {
|
||||
// OpenAI-compatible providers like Z.AI emit this exact format.
|
||||
// `\breason:` does not match `finish_reason:` because `_` is a word
|
||||
// character and there is no word boundary before `reason`.
|
||||
expectTimeoutFailoverSamples([
|
||||
"Provider finish_reason: network_error",
|
||||
"Provider finish_reason: abort",
|
||||
"Provider finish_reason: malformed_response",
|
||||
]);
|
||||
});
|
||||
|
||||
it("does not classify MALFORMED_FUNCTION_CALL as timeout", () => {
|
||||
const sample = "Unhandled stop reason: MALFORMED_FUNCTION_CALL";
|
||||
expect(isTimeoutErrorMessage(sample)).toBe(false);
|
||||
|
||||
@@ -114,6 +114,11 @@ const ERROR_PATTERNS = {
|
||||
/\bstop reason:\s*(?:abort|error|malformed_response|network_error)\b/i,
|
||||
/\breason:\s*(?:abort|error|malformed_response|network_error)\b/i,
|
||||
/\bunhandled stop reason:\s*(?:abort|error|malformed_response|network_error)\b/i,
|
||||
// OpenAI-compatible providers (e.g. Z.AI) surface transport-level errors as
|
||||
// `finish_reason: network_error` in the stream body. The `\breason:` pattern
|
||||
// above does NOT match `finish_reason:` because `_` is a word character so
|
||||
// there is no word boundary before `reason` in `finish_reason` (#61281).
|
||||
/\bfinish_reason:\s*(?:abort|error|malformed_response|network_error)\b/i,
|
||||
// AbortError messages from fetch/stream aborts (Ollama NDJSON stream
|
||||
// timeouts, signal aborts, etc.) — without these the flattened message
|
||||
// falls through to reason=unknown (#58315).
|
||||
|
||||
Reference in New Issue
Block a user