Fosowl/agenticSeek · error · Exception
Anthropic response is empty.
Error message
Anthropic response is empty.
What it means
Raised in anthropic_fn (sources/llm_provider.py:275) when client.messages.create() returns None instead of an Anthropic Message object. The library checks for None before accessing response.content[0].text and raises 'Anthropic response is empty.' to avoid a TypeError on the None response. Like the OpenAI path, it is immediately re-wrapped by the handler at line 281, so callers see 'Anthropic API error: Anthropic response is empty.'
Source
Thrown at sources/llm_provider.py:275
client = Anthropic(api_key=self.api_key)
system_message = None
messages = []
for message in history:
clean_message = {'role': message['role'], 'content': message['content']}
if message['role'] == 'system':
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(View on GitHub (pinned to ae57a23577)
Solutions
- Confirm the raw API works: curl https://api.anthropic.com/v1/messages with your key, model, and messages and inspect the JSON body.
- Check for proxies/gateways (HTTP_PROXY/HTTPS_PROXY, corporate middleboxes) that may return empty 200 responses; bypass them or fix their config.
- Upgrade the anthropic Python SDK so errors raise properly and responses deserialize correctly instead of yielding None.
- Verify the model name is a valid Anthropic model (e.g. claude-sonnet-4-20250514) and the API key is valid.
- If the error came from test code, fix the mock to return a realistic Message object rather than None.
Example fix
// before (test stub) client.messages.create = lambda **kw: None // after client.messages.create = lambda **kw: SimpleNamespace(content=[SimpleNamespace(text='stub reply')])
Defensive patterns
Strategy: type-guard
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 not r.content.strip():
raise RuntimeError("Anthropic endpoint returned an empty body (check proxies)")
r.raise_for_status() Type guard
def is_valid_anthropic_message(response) -> bool:
"""True only if the response has accessible content[0].text."""
if response is None:
return False
content = getattr(response, "content", None)
if not content:
return False
return isinstance(getattr(content[0], "text", None), str)
# usage
if not is_valid_anthropic_message(response):
raise RuntimeError("Anthropic response is empty or malformed.") Try / catch
import time
def anthropic_fn_with_retry(provider, history, retries=3):
try:
return provider.anthropic_fn(history)
except Exception as e:
cause = e.__cause__
if "response is empty" in str(e).lower():
raise RuntimeError(
"Anthropic returned an empty response; check proxies/gateway "
"and anthropic SDK version."
) from cause
if "429" in str(e) or "overloaded" in str(e).lower():
time.sleep(2 ** retries)
return provider.anthropic_fn(history)
raise Prevention
- Never stub API responses with None in tests — use objects shaped like real Anthropic Messages.
- Keep the anthropic SDK upgraded so errors raise as typed exceptions instead of returning None.
- Audit HTTP(S)_PROXY settings and corporate gateways that might return empty 200 bodies.
- Guard response.content[0].text access with a type/emptiness check.
- Validate the key and model with a minimal real request before running longer pipelines.
When it happens
Trigger: client.messages.create(model=self.model, max_tokens=1024, messages=messages, system=system_message) returns None — most plausible with a proxy/gateway or non-standard base URL returning an empty 200 body, or an SDK/server deserialization mismatch. Note this is the only non-message role filtering path: system messages are extracted into system_message before the call.
Common situations: Corporate proxy or API gateway intercepting requests and returning empty bodies; monkeypatched or outdated anthropic SDK returning None on error instead of raising; response stubs/mocks returning None in tests wired to real code; hitting a wrong base_url that responds 200 with empty content.
Related errors
- OpenAI response is empty.
- OpenRouter response is empty.
- MiniMax response is empty.
- Anthropic API error: {str(e)}
- Google response is empty.
AI-assisted analysis of Fosowl/agenticSeek@ae57a23577 (2026-08-30).
Data as JSON: /api/errors/6da5c4f0b5dafb40.
Report an issue: GitHub.