{"record":{"id":"bb765b9bda836306","repo":"Fosowl/agenticSeek","slug":"anthropic-api-error-str-e","errorCode":null,"errorMessage":"Anthropic API error: {str(e)}","messagePattern":"Anthropic API error: (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"sources/llm_provider.py","lineNumber":281,"sourceCode":"                system_message = message['content']\n            else:\n                messages.append(clean_message)\n\n        try:\n            response = client.messages.create(\n                model=self.model,\n                max_tokens=1024,\n                messages=messages,\n                system=system_message\n            )\n            if response is None:\n                raise Exception(\"Anthropic response is empty.\")\n            thought = response.content[0].text\n            if verbose:\n                print(thought)\n            return thought\n        except Exception as e:\n            raise Exception(f\"Anthropic API error: {str(e)}\") from e\n\n    def google_fn(self, history, verbose=False):\n        \"\"\"\n        Use google gemini to generate text.\n        \"\"\"\n        base_url = self.server_ip\n        if self.is_local:\n            raise Exception(\"Google Gemini is not available for local use. Change config.ini\")\n\n        client = OpenAI(api_key=self.api_key, base_url=\"https://generativelanguage.googleapis.com/v1beta/openai/\")\n        try:\n            response = client.chat.completions.create(\n                model=self.model,\n                messages=history,\n            )\n            if response is None:\n                raise Exception(\"Google response is empty.\")\n            thought = response.choices[0].message.content","sourceCodeStart":263,"sourceCodeEnd":299,"githubUrl":"https://github.com/Fosowl/agenticSeek/blob/ae57a2357745a9706cb12d0fd76d954c84d166fa/sources/llm_provider.py#L263-L299","documentation":"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__.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Read the wrapped str(e): 401 → fix the API key, 400 → fix the request payload, 429 → back off and retry, 529/5xx → retry later.","Verify ANTHROPIC_API_KEY (self.api_key) is set, active, and has available credit.","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.","Use a valid Anthropic model name (claude-* family), not an OpenAI model identifier.","Retry 429/overloaded errors with exponential backoff.","Log e.__cause__ to see the original anthropic SDK exception with request IDs for support/debugging."],"exampleFix":"// before: history = [{\"role\": \"system\", \"content\": \"You are helpful\"}]\n// after: include at least one user message\nhistory = [\n    {\"role\": \"system\", \"content\": \"You are helpful\"},\n    {\"role\": \"user\", \"content\": \"Hello!\"}\n]","handlingStrategy":"try-catch","validationCode":"import os, httpx\n\ndef assert_anthropic_ready(api_key=None, model=\"claude-sonnet-4-20250514\"):\n    key = api_key or os.environ.get(\"ANTHROPIC_API_KEY\")\n    if not key:\n        raise RuntimeError(\"ANTHROPIC_API_KEY is not set\")\n    r = httpx.post(\n        \"https://api.anthropic.com/v1/messages\",\n        headers={\"x-api-key\": key, \"anthropic-version\": \"2023-06-01\"},\n        json={\"model\": model, \"max_tokens\": 1, \"messages\": [{\"role\": \"user\", \"content\": \"hi\"}]},\n        timeout=10,\n    )\n    if r.status_code == 401:\n        raise RuntimeError(\"Anthropic API key is invalid\")\n    if r.status_code == 404:\n        raise RuntimeError(f\"Model '{model}' not found; use a claude-* model id\")\n    r.raise_for_status()","typeGuard":"def is_retryable_anthropic_error(err: BaseException) -> bool:\n    \"\"\"Transient errors worth retrying vs permanent request problems.\"\"\"\n    msg = str(err).lower()\n    return any(tok in msg for tok in (\"429\", \"rate limit\", \"overloaded\", \"529\", \"503\", \"timeout\"))","tryCatchPattern":"import time\n\ndef anthropic_fn_with_retry(provider, history, retries=4):\n    for attempt in range(retries):\n        try:\n            return provider.anthropic_fn(history)\n        except Exception as e:\n            if is_retryable_anthropic_error(e) and attempt < retries - 1:\n                time.sleep(2 ** attempt)\n                continue\n            if \"401\" in str(e) or \"authentication\" in str(e).lower():\n                raise RuntimeError(\"Fix ANTHROPIC_API_KEY (invalid/expired).\") from e.__cause__\n            if \"400\" in str(e) or \"invalid_request\" in str(e).lower():\n                raise RuntimeError(\n                    \"Bad request: ensure history has at least one non-system \"\n                    \"message and a valid claude-* model name.\"\n                ) from e.__cause__\n            raise","preventionTips":["Set and verify ANTHROPIC_API_KEY at startup; never hard-code it in source.","Always include at least one user/assistant message in history — system-only histories become an empty messages array and fail with 400.","Use valid Anthropic model ids (claude-*) rather than OpenAI-style names.","Retry 429/overloaded responses with exponential backoff instead of failing the whole run.","Log e.__cause__ (the anthropic SDK exception) to capture error codes and request IDs for debugging."],"tags":["anthropic","api-error","wrapped-exception","authentication","rate-limit"],"backgroundTag":"llm-api-call-failed","analyzedSha":"ae57a2357745a9706cb12d0fd76d954c84d166fa","analyzedAt":"2026-08-30T02:49:05.834Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}