From 4ac73677339da333e22c853066fcd5c57e537cec Mon Sep 17 00:00:00 2001 From: CRABHIVE Date: Sun, 5 Apr 2026 18:36:14 -0400 Subject: [PATCH] fix: include retry timing in 429 error messages (#366) ## Summary - Extract retry-after header from 429 API errors and include timing guidance in the user-facing error message - Previously, non-quota 429 errors showed a generic message with no guidance on when to retry, only a link to status.anthropic.com ## Impact - user-facing impact: 429 error messages now tell users when to retry instead of just linking to a status page - developer/maintainer impact: none ## Testing - [x] `bun run build` - [ ] `bun run smoke` - [ ] focused tests: error formatting is pure string construction, verified via build + manual inspection ## Notes - provider/model path tested: applies to all providers returning 429 - screenshots attached (if UI changed): n/a - follow-up work or known limitations: 529 errors could get similar treatment in a follow-up https://claude.ai/code/session_01D7kprMn4c66a5WrZscF7rv Co-authored-by: Claude --- src/services/api/errors.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/services/api/errors.ts b/src/services/api/errors.ts index c2a3512d..508213a3 100644 --- a/src/services/api/errors.ts +++ b/src/services/api/errors.ts @@ -557,8 +557,12 @@ export function getAssistantMessageFromError( const stripped = error.message.replace(/^429\s+/, '') const innerMessage = stripped.match(/"message"\s*:\s*"([^"]*)"/)?.[1] const detail = innerMessage || stripped + const retryAfter = (error as APIError).headers?.get?.('retry-after') + const retryHint = retryAfter && !isNaN(Number(retryAfter)) + ? `Try again in ${retryAfter} seconds.` + : 'Try again in a few seconds.' return createAssistantAPIErrorMessage({ - content: `${API_ERROR_MESSAGE_PREFIX}: Request rejected (429) · ${detail || `this may be a temporary capacity issue${getAPIProvider() === 'firstParty' ? ' — check status.anthropic.com' : ''}`}`, + content: `${API_ERROR_MESSAGE_PREFIX}: Request rejected (429) · ${detail || 'this may be a temporary capacity issue'} — ${retryHint}`, error: 'rate_limit', }) }