MemPalace/mempalace · error · LLMError
Unexpected response shape: {e}
Error message
Unexpected response shape: {e} What it means
LLMError raised by OpenAICompatProvider.classify() when the response JSON lacks the expected choices[0].message.content path (KeyError, IndexError, or TypeError during extraction). The server answered 200 with valid JSON, but the shape is not an OpenAI chat completion.
Source
Thrown at mempalace/llm_client.py:358
) -> LLMResponse:
body: dict = {
"model": self.model,
"messages": [
{"role": "system", "content": system},
{"role": "user", "content": user},
],
"temperature": 0.1,
}
if json_mode:
body["response_format"] = {"type": "json_object"}
headers = {}
if self.api_key:
headers["Authorization"] = f"Bearer {self.api_key}"
data = _http_post_json(self._resolve_url(), body, headers=headers, timeout=self.timeout)
try:
text = data["choices"][0]["message"]["content"]
except (KeyError, IndexError, TypeError) as e:
raise LLMError(f"Unexpected response shape: {e}") from e
if not text:
raise LLMError(f"Empty response from {self.name} (model={self.model})")
return LLMResponse(text=text, model=self.model, provider=self.name, raw=data)
# ==================== ANTHROPIC ====================
class AnthropicProvider(LLMProvider):
name = "anthropic"
DEFAULT_ENDPOINT = "https://api.anthropic.com"
API_VERSION = "2023-06-01"
def __init__(
self,
model: str,
api_key: Optional[str] = None,
endpoint: Optional[str] = None,View on GitHub (pinned to 06cb6987f0)
Solutions
- Inspect the raw body (it is in e.__cause__ context or reproduce with curl) to see the actual schema
- For Ollama, either use the ollama provider or its OpenAI-compatible /v1 route
- Ensure the URL resolves to a true /v1/chat/completions endpoint
- Update or pin a server version whose response format matches OpenAI's
Example fix
# before
provider = build_provider("openai-compat", model="llama3", endpoint="http://localhost:11434")
# server returns native Ollama schema {"message": ...} -> Unexpected response shape: 'choices'
# after
provider = build_provider("ollama", model="llama3", endpoint="http://localhost:11434") Defensive patterns
Strategy: validation
Validate before calling
import json, urllib.request
def looks_like_openai_chat(url, body, timeout=10):
req = urllib.request.Request(url, data=json.dumps(body).encode(), headers={"Content-Type": "application/json"})
with urllib.request.urlopen(req, timeout=timeout) as r:
data = json.loads(r.read())
return isinstance(data.get("choices"), list) and data["choices"] Try / catch
from mempalace.llm_client import LLMError
try:
resp = provider.classify(s, u)
except LLMError as e:
if "Unexpected response shape" in str(e):
# endpoint is not speaking OpenAI chat schema — switch provider or fix URL
raise
raise Prevention
- Smoke-test a new endpoint with one classify() call before batch runs
- Match provider name to server type: ollama for native Ollama, openai-compat only for true /v1/chat/completions servers
When it happens
Trigger: Pointing --llm-endpoint at a server that returns a different schema: an Ollama native API response ({message: {...}} without choices), a completions-style response, or an error object with HTTP 200.
Common situations: Using the Ollama base URL (localhost:11434) with the openai-compat provider instead of its /v1 compatibility layer; mixing up completions vs chat endpoints; server versions that change response fields; gateway wrapping responses in {data: ...}.
Related errors
- HTTP {e.code} from {url}: {detail or e.reason}
- Malformed response from {url}: {e}
- openai-compat provider requires --llm-endpoint
- Empty response from {self.name} (model={self.model})
- LLM_ENDPOINT must use http:// or https:// (got scheme {schem
AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15).
Data as JSON: /api/errors/7591d698d9c125d6.
Report an issue: GitHub.