MemPalace/mempalace · error · LLMError
Malformed response from {url}: {e}
Error message
Malformed response from {url}: {e} What it means
LLMError raised when the LLM endpoint returns HTTP 200 but the body is not valid JSON (json.JSONDecodeError). The provider pipeline assumes every successful response parses, so a non-JSON body — an HTML error page, a proxy login page, truncated output — surfaces here.
Source
Thrown at mempalace/llm_client.py:199
req = Request(
url,
data=json.dumps(body).encode("utf-8"),
headers={"Content-Type": "application/json", **headers},
)
try:
with urlopen(req, timeout=timeout) as resp:
return json.loads(resp.read())
except HTTPError as e:
detail = ""
try:
detail = e.read().decode("utf-8", errors="replace")[:500]
except Exception:
pass
raise LLMError(f"HTTP {e.code} from {url}: {detail or e.reason}") from e
except (URLError, OSError) as e:
raise LLMError(f"Cannot reach {url}: {e}") from e
except json.JSONDecodeError as e:
raise LLMError(f"Malformed response from {url}: {e}") from e
# ==================== OLLAMA ====================
class OllamaProvider(LLMProvider):
name = "ollama"
DEFAULT_ENDPOINT = "http://localhost:11434"
def __init__(
self,
model: str,
endpoint: Optional[str] = None,
timeout: int = 180,
num_ctx: Optional[int] = None,
**_: object,
):
super().__init__(View on GitHub (pinned to 06cb6987f0)
Solutions
- curl the endpoint with the same payload and inspect the raw body — it is usually HTML/plain text, revealing the real culprit
- Fix the endpoint URL to target the API server, not a web UI or proxy login page
- Bypass or configure the intercepting proxy for this host
- If the body is truncated JSON, check gateway/proxy response size limits
Defensive patterns
Strategy: retry
Try / catch
from mempalace.llm_client import LLMError
try:
resp = provider.classify(system, user)
except LLMError as e:
if "Malformed response" in str(e):
# body was not JSON — dump context for debugging, do not blind-retry
log.error("non-JSON response from %s — check proxy/gateway", provider.endpoint)
raise Prevention
- Verify the endpoint returns JSON with a one-off curl before wiring it in
- Exclude LLM endpoints from HTML-rewriting proxies and captive portals
- Pin server versions whose response format you have tested
When it happens
Trigger: A proxy or captive portal intercepting the request and returning HTML; an OpenAI-compatible server that returns plain-text errors with status 200; a response truncated by a gateway so the JSON is cut mid-string.
Common situations: Corporate proxies rewriting responses; pointing --llm-endpoint at a web UI instead of the API port (e.g. LM Studio UI port vs API port); reverse proxies (nginx/traefik) emitting error pages; version mismatch where the server changed its response format.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Qdrant returned invalid JSON
- HTTP {e.code} from {url}: {detail or e.reason}
- daemon returned non-JSON response: {raw[:200]!r}
- Embedding API request to {self._url} failed: {e}. Check that
- Cannot reach {url}: {e}
AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15).
Data as JSON: /api/errors/5967e5c220961843.
Report an issue: GitHub.