mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-05 03:10:22 +00:00
fix(agents): normalize abort-wrapped RESOURCE_EXHAUSTED into failover errors (#11972)
This commit is contained in:
committed by
Darshil
parent
2f5d3b6574
commit
dac220bd88
@@ -72,9 +72,16 @@ function getStatusCode(err: unknown): number | undefined {
|
||||
if (!err || typeof err !== "object") {
|
||||
return undefined;
|
||||
}
|
||||
// Dig into nested `err.error` shapes (e.g. Google Vertex abort wrappers)
|
||||
const nestedError =
|
||||
"error" in err && err.error && typeof err.error === "object"
|
||||
? (err.error as { status?: unknown; code?: unknown })
|
||||
: undefined;
|
||||
const candidate =
|
||||
(err as { status?: unknown; statusCode?: unknown }).status ??
|
||||
(err as { statusCode?: unknown }).statusCode;
|
||||
(err as { statusCode?: unknown }).statusCode ??
|
||||
nestedError?.code ??
|
||||
nestedError?.status;
|
||||
if (typeof candidate === "number") {
|
||||
return candidate;
|
||||
}
|
||||
@@ -88,7 +95,11 @@ function getErrorCode(err: unknown): string | undefined {
|
||||
if (!err || typeof err !== "object") {
|
||||
return undefined;
|
||||
}
|
||||
const candidate = (err as { code?: unknown }).code;
|
||||
const nestedError =
|
||||
"error" in err && err.error && typeof err.error === "object"
|
||||
? (err.error as { code?: unknown; status?: unknown })
|
||||
: undefined;
|
||||
const candidate = (err as { code?: unknown }).code ?? nestedError?.status ?? nestedError?.code;
|
||||
if (typeof candidate !== "string") {
|
||||
return undefined;
|
||||
}
|
||||
@@ -114,10 +125,53 @@ function getErrorMessage(err: unknown): string {
|
||||
if (typeof message === "string") {
|
||||
return message;
|
||||
}
|
||||
// Extract message from nested `err.error.message` (e.g. Google Vertex wrappers)
|
||||
const nestedMessage =
|
||||
"error" in err &&
|
||||
err.error &&
|
||||
typeof err.error === "object" &&
|
||||
typeof (err.error as { message?: unknown }).message === "string"
|
||||
? ((err.error as { message: string }).message ?? "")
|
||||
: "";
|
||||
if (nestedMessage) {
|
||||
return nestedMessage;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
function getErrorCause(err: unknown): unknown {
|
||||
if (!err || typeof err !== "object" || !("cause" in err)) {
|
||||
return undefined;
|
||||
}
|
||||
return (err as { cause?: unknown }).cause;
|
||||
}
|
||||
|
||||
/** Classify rate-limit / overloaded from symbolic error codes like RESOURCE_EXHAUSTED. */
|
||||
function classifyFailoverReasonFromSymbolicCode(raw: string | undefined): FailoverReason | null {
|
||||
const normalized = raw?.trim().toUpperCase();
|
||||
if (!normalized) {
|
||||
return null;
|
||||
}
|
||||
switch (normalized) {
|
||||
case "RESOURCE_EXHAUSTED":
|
||||
case "RATE_LIMIT":
|
||||
case "RATE_LIMITED":
|
||||
case "RATE_LIMIT_EXCEEDED":
|
||||
case "TOO_MANY_REQUESTS":
|
||||
case "THROTTLED":
|
||||
case "THROTTLING":
|
||||
case "THROTTLINGEXCEPTION":
|
||||
case "THROTTLING_EXCEPTION":
|
||||
return "rate_limit";
|
||||
case "OVERLOADED":
|
||||
case "OVERLOADED_ERROR":
|
||||
return "overloaded";
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function hasTimeoutHint(err: unknown): boolean {
|
||||
if (!err) {
|
||||
return false;
|
||||
@@ -160,6 +214,12 @@ export function resolveFailoverReasonFromError(err: unknown): FailoverReason | n
|
||||
return statusReason;
|
||||
}
|
||||
|
||||
// Check symbolic error codes (e.g. RESOURCE_EXHAUSTED from Google APIs)
|
||||
const symbolicCodeReason = classifyFailoverReasonFromSymbolicCode(getErrorCode(err));
|
||||
if (symbolicCodeReason) {
|
||||
return symbolicCodeReason;
|
||||
}
|
||||
|
||||
const code = (getErrorCode(err) ?? "").toUpperCase();
|
||||
if (
|
||||
[
|
||||
@@ -181,6 +241,14 @@ export function resolveFailoverReasonFromError(err: unknown): FailoverReason | n
|
||||
if (isTimeoutError(err)) {
|
||||
return "timeout";
|
||||
}
|
||||
// Walk into error cause chain (e.g. AbortError wrapping a rate-limit cause)
|
||||
const cause = getErrorCause(err);
|
||||
if (cause && cause !== err) {
|
||||
const causeReason = resolveFailoverReasonFromError(cause);
|
||||
if (causeReason) {
|
||||
return causeReason;
|
||||
}
|
||||
}
|
||||
if (!message) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user