From 0b6dfd0bbfab26f47082f0fe3194115ebcb7ff29 Mon Sep 17 00:00:00 2001 From: Tibsfox Date: Mon, 6 Apr 2026 18:22:02 -0700 Subject: [PATCH] fix(gsd): extract real error from message content when errorMessage is useless When errorMessage is uninformative (e.g. "success", "ok"), fall back to the assistant message text content for display while keeping rawErrorMsg for classification to avoid prose false-positives. Fixes #3588 Co-Authored-By: Claude Opus 4.6 (1M context) --- .../extensions/gsd/bootstrap/agent-end-recovery.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts b/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts index c5b9555a3..b3c517356 100644 --- a/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +++ b/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts @@ -100,16 +100,19 @@ export async function handleAgentEnd( // errorMessage looks uninformative. const rawErrorMsg = ("errorMessage" in lastMsg && lastMsg.errorMessage) ? String(lastMsg.errorMessage) : ""; const isUseless = !rawErrorMsg || /^(success|ok|true|error|unknown)$/i.test(rawErrorMsg.trim()); - let errorMsg = rawErrorMsg; + // #3588: When errorMessage is uninformative, extract the real error from + // the assistant message text content for display purposes only. + // Classification still uses rawErrorMsg to avoid false positives from prose. + let displayMsg = rawErrorMsg; if (isUseless && "content" in lastMsg && Array.isArray(lastMsg.content)) { const textBlock = lastMsg.content.find((b: any) => b.type === "text" && b.text); - if (textBlock) errorMsg = (textBlock as any).text.slice(0, 300); + if (textBlock) displayMsg = (textBlock as any).text.slice(0, 300); } - const errorDetail = errorMsg ? `: ${errorMsg}` : ""; + const errorDetail = displayMsg ? `: ${displayMsg}` : ""; const explicitRetryAfterMs = ("retryAfterMs" in lastMsg && typeof lastMsg.retryAfterMs === "number") ? lastMsg.retryAfterMs : undefined; - // ── 1. Classify ────────────────────────────────────────────────────── - const cls = classifyError(errorMsg, explicitRetryAfterMs); + // ── 1. Classify using rawErrorMsg to avoid prose false-positives ──── + const cls = classifyError(rawErrorMsg, explicitRetryAfterMs); // Cap rate-limit backoff for CLI-style providers (openai-codex, google-gemini-cli) // which use per-user quotas with shorter windows (#2922).