fix(gsd): extract real error from message content when errorMessage is useless

When errorMessage is uninformative (e.g. "success", "ok", "error"),
fall back to the assistant message text content to surface the real
provider error like "Invalid API key · Please run /login".

Fixes #3588

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Tibsfox 2026-04-06 18:20:11 -07:00
parent b4c6229360
commit eaeced4774

View file

@ -95,8 +95,17 @@ export async function handleAgentEnd(
return;
}
if (lastMsg && "stopReason" in lastMsg && lastMsg.stopReason === "error") {
const errorDetail = "errorMessage" in lastMsg && lastMsg.errorMessage ? `: ${lastMsg.errorMessage}` : "";
const errorMsg = ("errorMessage" in lastMsg && lastMsg.errorMessage) ? String(lastMsg.errorMessage) : "";
// #3588: errorMessage can be useless (e.g. "success") while the real error
// is in the assistant message text content. Fall back to content when
// 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;
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);
}
const errorDetail = errorMsg ? `: ${errorMsg}` : "";
const explicitRetryAfterMs = ("retryAfterMs" in lastMsg && typeof lastMsg.retryAfterMs === "number") ? lastMsg.retryAfterMs : undefined;
// ── 1. Classify ──────────────────────────────────────────────────────