From e97efdd73278ccee8095f3ffc455684c1d8c32f0 Mon Sep 17 00:00:00 2001 From: Saurabh Date: Wed, 25 Mar 2026 20:54:09 +0530 Subject: [PATCH] fix: strip HTTP status code prefix from surfaced rate limit messages --- .../pi-embedded-helpers.formatassistanterrortext.test.ts | 8 ++++++++ src/agents/pi-embedded-helpers/errors.ts | 4 +++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/agents/pi-embedded-helpers.formatassistanterrortext.test.ts b/src/agents/pi-embedded-helpers.formatassistanterrortext.test.ts index 5346f1a830b..0b4a1c14641 100644 --- a/src/agents/pi-embedded-helpers.formatassistanterrortext.test.ts +++ b/src/agents/pi-embedded-helpers.formatassistanterrortext.test.ts @@ -147,6 +147,14 @@ describe("formatAssistantErrorText", () => { ); }); + it("strips leading HTTP status code prefix from non-JSON rate limit messages", () => { + const msg = makeAssistantError("429 Your quota has been exhausted, try again in 24 hours"); + const result = formatAssistantErrorText(msg); + expect(result).toContain("try again in 24 hours"); + expect(result).not.toMatch(/^⚠️ 429\b/); + expect(result).toBe("⚠️ Your quota has been exhausted, try again in 24 hours"); + }); + it("returns a friendly message for empty stream chunk errors", () => { const msg = makeAssistantError("request ended without sending any chunks"); expect(formatAssistantErrorText(msg)).toBe("LLM request timed out."); diff --git a/src/agents/pi-embedded-helpers/errors.ts b/src/agents/pi-embedded-helpers/errors.ts index b7df985e379..0132fa33998 100644 --- a/src/agents/pi-embedded-helpers/errors.ts +++ b/src/agents/pi-embedded-helpers/errors.ts @@ -68,7 +68,9 @@ const RATE_LIMIT_SPECIFIC_HINT_RE = function extractProviderRateLimitMessage(raw: string): string | undefined { // Try to pull a human-readable message out of a JSON error payload first. const info = parseApiErrorInfo(raw); - const candidate = info?.message ?? raw; + // When the raw string is not a JSON payload, strip any leading HTTP status + // code (e.g. "429 ") so the surfaced message stays clean. + const candidate = info?.message ?? (extractLeadingHttpStatus(raw.trim())?.rest || raw); if (!candidate || !RATE_LIMIT_SPECIFIC_HINT_RE.test(candidate)) { return undefined;