MemPalace/mempalace · error · BackendError

Qdrant returned invalid JSON

Error message

Qdrant returned invalid JSON

What it means

Raised by QdrantClient.request() when the Qdrant server answered the HTTP request with a 200-level response whose body is not valid JSON. The REST client expects JSON on every endpoint; a body that fails json.loads raises BackendError.

Source

Thrown at mempalace/backends/qdrant.py:406

            headers["api-key"] = self._config.api_key
        if body is not None:
            data = json.dumps(body, ensure_ascii=False).encode("utf-8")
        req = urlrequest.Request(url, data=data, method=method, headers=headers)
        try:
            with urlrequest.urlopen(req, timeout=self._config.timeout) as resp:
                raw = resp.read()
        except urlerror.HTTPError as exc:
            raw = exc.read()
            detail = raw.decode("utf-8", errors="replace") if raw else str(exc)
            raise _QdrantHTTPError(exc.code, detail) from exc
        except urlerror.URLError as exc:
            raise BackendError(f"Qdrant request failed: {exc.reason}") from exc
        if not raw:
            return {}
        try:
            return json.loads(raw.decode("utf-8"))
        except json.JSONDecodeError as exc:
            raise BackendError("Qdrant returned invalid JSON") from exc

    def collection_exists(self, collection: str) -> bool:
        try:
            self.request("GET", f"/collections/{urlparse.quote(collection, safe='')}")
        except _QdrantHTTPError as exc:
            if exc.status == 404:
                return False
            raise
        return True

    def get_collection_info(self, collection: str) -> dict:
        return self.request("GET", f"/collections/{urlparse.quote(collection, safe='')}")

    def create_collection(self, collection: str, dimension: int) -> None:
        self.request(
            "PUT",
            f"/collections/{urlparse.quote(collection, safe='')}",
            body={"vectors": {"size": int(dimension), "distance": "Cosine"}},

View on GitHub (pinned to 06cb6987f0)

Solutions

  1. curl the exact URL the client uses and inspect the raw body: curl -s http://host:6333/collections | head -c 500
  2. If a proxy returns HTML, fix proxy routing/auth so /collections/* reaches Qdrant directly
  3. Verify the URL points at a real Qdrant instance (GET / should return Qdrant version JSON)
  4. Retry once — truncation from transient network faults is usually not reproducible
  5. Check proxy buffering/caching settings (proxy_buffering off, no cache for API paths)
Defensive patterns

Strategy: try-catch

Try / catch

from mempalace.backends.base import BackendError
try:
    info = client.request("GET", "/collections")
except BackendError as e:
    if "invalid JSON" in str(e):
        # proxy or wrong endpoint answered; inspect raw response with curl

Prevention

When it happens

Trigger: A proxy (nginx, corporate MITM, service mesh sidecar) returns an HTML error/login page with 200 status; the URL actually points at a non-Qdrant service; a truncated response due to a connection cut after headers; a server version returning plain-text on some endpoint.

Common situations: Reverse proxy in front of Qdrant intercepting requests and returning HTML auth pages; pointing the config at the wrong service that answers 200 with HTML; flaky network truncating the body; proxy_cache serving corrupted content.

Understand the failure class

Related errors


AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15). Data as JSON: /api/errors/6fab7cc256bb83ed. Report an issue: GitHub.