{"record":{"id":"ba62eae1b4bacea1","repo":"bytedance/deer-flow","slug":"mem0-method-path-returned-malformed-json-e","errorCode":null,"errorMessage":"mem0 {method} {path} returned malformed JSON: {e}","messagePattern":"mem0 (.+?) (.+?) returned malformed JSON: (.+?)","errorType":"exception","errorClass":"Mem0APIError","httpStatus":null,"severity":"error","filePath":"backend/packages/harness/deerflow/agents/memory/backends/mem0/client.py","lineNumber":59,"sourceCode":"\n    def close(self) -> None:\n        self._http.close()\n\n    def _request(self, method: str, path: str, **kwargs: Any) -> dict[str, Any]:\n        try:\n            resp = self._http.request(method, path, **kwargs)\n        except httpx.HTTPError as e:\n            raise Mem0APIError(f\"mem0 request failed: {e}\") from e\n        if resp.status_code == 401:\n            raise Mem0AuthError(\"mem0 authentication failed (check the API key)\")\n        if resp.status_code >= 400:\n            raise Mem0APIError(f\"mem0 {method} {path} -> {resp.status_code}: {resp.text[:200]}\")\n        if not resp.content:\n            return {}\n        try:\n            return resp.json()\n        except json.JSONDecodeError as e:\n            raise Mem0APIError(f\"mem0 {method} {path} returned malformed JSON: {e}\") from e\n\n    def add_memories(\n        self,\n        *,\n        messages: list[dict[str, str]],\n        user_id: str | None = None,\n        agent_id: str | None = None,\n        run_id: str | None = None,\n    ) -> dict[str, Any]:\n        \"\"\"Queue extraction (async server-side; response carries an event_id).\"\"\"\n        body: dict[str, Any] = {\"messages\": messages}\n        if user_id:\n            body[\"user_id\"] = user_id\n        if agent_id:\n            body[\"agent_id\"] = agent_id\n        if run_id:\n            body[\"run_id\"] = run_id\n        return self._request(\"POST\", \"/v3/memories/add/\", json=body)","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/packages/harness/deerflow/agents/memory/backends/mem0/client.py#L41-L77","documentation":"Raised as Mem0APIError by Mem0Client._request when the server returns HTTP < 400 with a non-empty body that is not valid JSON (json.JSONDecodeError on resp.json()). The client expects JSON responses ('Accept: application/json'); malformed JSON means something other than the real mem0 API answered — or the response stream was corrupted/truncated.","triggerScenarios":"A request succeeds status-wise but the body is HTML (captive portal, proxy error page, a reverse proxy serving the frontend on the same host), a truncated response from a flaky proxy, or a misconfigured base_url landing on a non-API server.","commonSituations":"Corporate proxy or Wi-Fi captive portal intercepting HTTPS and returning an HTML page; base_url pointing at a web UI instead of the API; self-hosted ingress misrouting /memories traffic to a static server; response compression handled incorrectly by an intermediate proxy.","solutions":["curl the base_url from the Gateway host and inspect Content-Type/body — if you get HTML, the URL or the proxy is wrong","Fix base_url to point directly at the mem0 API root, bypassing any UI-serving host or path","Exclude the mem0 host from corporate proxy interception (NO_PROXY) or configure the proxy correctly","If self-hosted behind nginx/ingress, verify the route proxies to the mem0 service and passes Accept/Content-Type headers untouched"],"exampleFix":"# before\nexport HTTPS_PROXY=http://proxy.corp:3128   # intercepts api.mem0.ai, returns HTML\n\n# after\nexport HTTPS_PROXY=http://proxy.corp:3128\nexport NO_PROXY=api.mem0.ai   # or fix base_url to the real API host","handlingStrategy":"try-catch","validationCode":"import httpx\n\ndef mem0_returns_json(base_url: str) -> bool:\n    try:\n        r = httpx.get(base_url, timeout=5, headers={\"Accept\": \"application/json\"})\n        ct = r.headers.get(\"content-type\", \"\")\n        return \"json\" in ct or r.content[:1] in (b\"{\", b\"[\")\n    except httpx.HTTPError:\n        return False","typeGuard":null,"tryCatchPattern":"from deerflow.agents.memory.backends.mem0.client import Mem0APIError\n\ntry:\n    data = client.get_context(user_id=u)\nexcept Mem0APIError as e:\n    if \"malformed JSON\" in str(e):\n        # something other than the mem0 API answered (proxy/captive portal/wrong URL)\n        # do NOT retry — diagnose the base_url/proxy path first\n        raise RuntimeError(f\"non-API endpoint answered at base_url: {e}\") from e\n    raise","preventionTips":["Smoke-test base_url with curl -H 'Accept: application/json' and confirm a JSON body before enabling the backend","Exclude the mem0 host from intercepting proxies (NO_PROXY) in corporate networks","Self-hosted: verify ingress routes the API prefix to the mem0 service, not a UI/static server"],"tags":["mem0","memory","json","proxy","http"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}