From 5428422b6ca90471ac2f41fd6fdc0b6a55636a8b Mon Sep 17 00:00:00 2001 From: ajmallesh Date: Fri, 16 Jan 2026 11:18:27 -0800 Subject: [PATCH] fix: add universal billing error detection for router mode - Add HTTP 402 and 'insufficient credits' patterns to error classification - Detect provider billing errors in both exception and message content paths --- src/ai/message-handlers.ts | 3 +++ src/error-handling.ts | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/ai/message-handlers.ts b/src/ai/message-handlers.ts index b57ffa3..6a8418c 100644 --- a/src/ai/message-handlers.ts +++ b/src/ai/message-handlers.ts @@ -60,12 +60,15 @@ export function detectApiError(content: string): ApiErrorDetection { // When Claude Code hits its spending cap, it returns a short message like // "Spending cap reached resets 8am" instead of throwing an error. // These should retry with 5-30 min backoff so workflows can recover when cap resets. + // Also catches provider billing errors (OpenRouter 402, etc.) that appear in message content. const BILLING_PATTERNS = [ 'spending cap', 'spending limit', 'cap reached', 'budget exceeded', 'usage limit', + '402', // HTTP Payment Required (universal) + 'insufficient credits', // OpenRouter ]; const isBillingError = BILLING_PATTERNS.some((pattern) => diff --git a/src/error-handling.ts b/src/error-handling.ts index ac605a5..3f00131 100644 --- a/src/error-handling.ts +++ b/src/error-handling.ts @@ -211,7 +211,9 @@ export function classifyErrorForTemporal(error: unknown): TemporalErrorClassific // === BILLING ERRORS (Retryable with long backoff) === // Anthropic returns billing as 400 invalid_request_error // Human can add credits OR wait for spending cap to reset (5-30 min backoff) + // 402 is HTTP "Payment Required" - universal across providers (OpenRouter, etc.) if ( + message.includes('402') || message.includes('billing_error') || message.includes('credit balance is too low') || message.includes('insufficient credits') ||