Skip to content

Robustness: detect retryable HTTP errors from structured SDK fields, not message strings #47

Description

@zjshen14

Problem

Both GeminiClient and AnthropicClient classify retryable errors by scanning the error message string:

// src/model/gemini.ts:63
const isRetryable =
  msg.includes("429") || msg.includes("500") || msg.includes("RESOURCE_EXHAUSTED");

// src/model/anthropic.ts:69
const isRetryable =
  msg.includes("429") || msg.includes("500") || msg.includes("overloaded");

Error message text is not a stable API — SDK version bumps, proxy wrappers, or locale changes can alter the message format. A retry that should fire won't, and hard errors may be silently retried.

Expected behavior

Retry classification should use the structured status field on the SDK error object, which is stable across SDK versions.

Fix

Use the SDK's typed error classes:

// Anthropic
import Anthropic from "@anthropic-ai/sdk";
const isRetryable =
  err instanceof Anthropic.APIError && [429, 500, 502, 529].includes(err.status);

// Gemini — GoogleGenerativeAIError exposes .status
import { GoogleGenerativeAIError } from "@google/generative-ai";
const isRetryable =
  err instanceof GoogleGenerativeAIError && [429, 500, 502, 503].includes(err.status ?? 0);

Location

  • src/model/gemini.ts:63
  • src/model/anthropic.ts:69

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinggood first issueGood for newcomers

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions