Fosowl/agenticSeek · error · Exception

Anthropic API error: {str(e)}

Error message

Anthropic API error: {str(e)}

What it means

This is the catch-all wrapper in anthropic_fn (sources/llm_provider.py:281): any exception in the try block — SDK errors such as 401 authentication_error, 429 rate_limit_error, 400 invalid_request_error, 5xx overloaded_error, the library's own 'Anthropic response is empty.' check, or a TypeError from response.content[0] — is re-raised as Exception(f"Anthropic API error: {str(e)}") with the original attached as __cause__.

Source

Thrown at sources/llm_provider.py:281

                system_message = message['content']
            else:
                messages.append(clean_message)

        try:
            response = client.messages.create(
                model=self.model,
                max_tokens=1024,
                messages=messages,
                system=system_message
            )
            if response is None:
                raise Exception("Anthropic response is empty.")
            thought = response.content[0].text
            if verbose:
                print(thought)
            return thought
        except Exception as e:
            raise Exception(f"Anthropic API error: {str(e)}") from e

    def google_fn(self, history, verbose=False):
        """
        Use google gemini to generate text.
        """
        base_url = self.server_ip
        if self.is_local:
            raise Exception("Google Gemini is not available for local use. Change config.ini")

        client = OpenAI(api_key=self.api_key, base_url="https://generativelanguage.googleapis.com/v1beta/openai/")
        try:
            response = client.chat.completions.create(
                model=self.model,
                messages=history,
            )
            if response is None:
                raise Exception("Google response is empty.")
            thought = response.choices[0].message.content

View on GitHub (pinned to ae57a23577)

Solutions

  1. Read the wrapped str(e): 401 → fix the API key, 400 → fix the request payload, 429 → back off and retry, 529/5xx → retry later.
  2. Verify ANTHROPIC_API_KEY (self.api_key) is set, active, and has available credit.
  3. Ensure history contains at least one non-system user/assistant message — the code extracts system messages into system_message and an all-system history yields an empty messages array that the API rejects.
  4. Use a valid Anthropic model name (claude-* family), not an OpenAI model identifier.
  5. Retry 429/overloaded errors with exponential backoff.
  6. Log e.__cause__ to see the original anthropic SDK exception with request IDs for support/debugging.

Example fix

// before: history = [{"role": "system", "content": "You are helpful"}]
// after: include at least one user message
history = [
    {"role": "system", "content": "You are helpful"},
    {"role": "user", "content": "Hello!"}
]
Defensive patterns

Strategy: try-catch

Validate before calling

import os, httpx

def assert_anthropic_ready(api_key=None, model="claude-sonnet-4-20250514"):
    key = api_key or os.environ.get("ANTHROPIC_API_KEY")
    if not key:
        raise RuntimeError("ANTHROPIC_API_KEY is not set")
    r = httpx.post(
        "https://api.anthropic.com/v1/messages",
        headers={"x-api-key": key, "anthropic-version": "2023-06-01"},
        json={"model": model, "max_tokens": 1, "messages": [{"role": "user", "content": "hi"}]},
        timeout=10,
    )
    if r.status_code == 401:
        raise RuntimeError("Anthropic API key is invalid")
    if r.status_code == 404:
        raise RuntimeError(f"Model '{model}' not found; use a claude-* model id")
    r.raise_for_status()

Type guard

def is_retryable_anthropic_error(err: BaseException) -> bool:
    """Transient errors worth retrying vs permanent request problems."""
    msg = str(err).lower()
    return any(tok in msg for tok in ("429", "rate limit", "overloaded", "529", "503", "timeout"))

Try / catch

import time

def anthropic_fn_with_retry(provider, history, retries=4):
    for attempt in range(retries):
        try:
            return provider.anthropic_fn(history)
        except Exception as e:
            if is_retryable_anthropic_error(e) and attempt < retries - 1:
                time.sleep(2 ** attempt)
                continue
            if "401" in str(e) or "authentication" in str(e).lower():
                raise RuntimeError("Fix ANTHROPIC_API_KEY (invalid/expired).") from e.__cause__
            if "400" in str(e) or "invalid_request" in str(e).lower():
                raise RuntimeError(
                    "Bad request: ensure history has at least one non-system "
                    "message and a valid claude-* model name."
                ) from e.__cause__
            raise

Prevention

When it happens

Trigger: Any failure during client.messages.create(model=self.model, max_tokens=1024, messages=messages, system=system_message): invalid API key, model name typo, empty/invalid messages list (e.g. history containing only a system message, which is stripped into system_message leaving messages empty), max_tokens/param issues, rate limits, or empty-response/None-content access failures.

Common situations: ANTHROPIC_API_KEY missing/expired/incorrect in config or env; using an OpenAI-style model name ('gpt-4') with the Anthropic provider; history made up solely of system-role messages so the required messages array is empty (400 invalid_request_error); hitting 429 rate limits during bursts; max_tokens smaller than the model minimum; SDK version incompatible with the current API.

Related errors


AI-assisted analysis of Fosowl/agenticSeek@ae57a23577 (2026-08-30). Data as JSON: /api/errors/bb765b9bda836306. Report an issue: GitHub.