{"record":{"id":"f0a4ac6fd8c8b75b","repo":"chroma-core/chroma","slug":"unexpected-error-calling-chroma-cloud-api-e","errorCode":null,"errorMessage":"Unexpected error calling Chroma Cloud API: {e}","messagePattern":"Unexpected error calling Chroma Cloud API: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"chromadb/utils/embedding_functions/chroma_cloud_splade_embedding_function.py","lineNumber":112,"sourceCode":"        }\n\n        try:\n            import httpx\n\n            response = self._session.post(self._api_url, json=payload, timeout=60)\n            response.raise_for_status()\n            json_response = response.json()\n            return self._parse_response(json_response)\n        except httpx.HTTPStatusError as e:\n            raise RuntimeError(\n                f\"Failed to get embeddings from Chroma Cloud API: HTTP {e.response.status_code} - {e.response.text}\"\n            )\n        except httpx.TimeoutException:\n            raise RuntimeError(\"Request to Chroma Cloud API timed out after 60 seconds\")\n        except httpx.HTTPError as e:\n            raise RuntimeError(f\"Failed to get embeddings from Chroma Cloud API: {e}\")\n        except Exception as e:\n            raise RuntimeError(f\"Unexpected error calling Chroma Cloud API: {e}\")\n\n    def _parse_response(self, response: Any) -> SparseVectors:\n        \"\"\"\n        Parse the response from the Chroma Cloud Sparse Embedding API.\n        \"\"\"\n        raw_embeddings = response[\"embeddings\"]\n\n        # Normalize each sparse vector (sort indices and validate)\n        normalized_vectors: SparseVectors = []\n        for emb in raw_embeddings:\n            # Handle both dict format and SparseVector format\n            if isinstance(emb, dict):\n                indices = emb.get(\"indices\", [])\n                values = emb.get(\"values\", [])\n                raw_labels = emb.get(\"labels\") if self.include_tokens else None\n                labels: Optional[List[str]] = raw_labels if raw_labels else None\n            else:\n                # Already a SparseVector, extract its data","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/chromadb/utils/embedding_functions/chroma_cloud_splade_embedding_function.py#L94-L130","documentation":"The final except Exception clause in __call__ is a catch-all: anything that is not an httpx HTTPStatusError, TimeoutException, or HTTPError — malformed JSON in the response, KeyError/TypeError while parsing an unexpected payload, errors raised by _parse_response normalizing sparse vectors — is re-raised as RuntimeError prefixed with 'Unexpected error'. The original exception's text is preserved after the colon.","triggerScenarios":"Calling ef(texts) when the server replies 200 with a non-JSON or truncated body (response.json() raises), or with JSON whose 'embeddings' entries have an unexpected shape that breaks _parse_response/normalize_sparse_vector.","commonSituations":"Proxies or captive portals injecting HTML; truncated responses on flaky links; API contract changes on the Chroma Cloud side; payloads where sparse vectors contain duplicate or out-of-range indices.","solutions":["Inspect the text after 'Unexpected error:' — it names the real underlying exception (e.g. JSONDecodeError, KeyError).","Reproduce the request manually (POST to the _api_url with the EF's headers) to inspect the raw body.","If a proxy is mangling responses, bypass or correctly configure it.","Report contract mismatches to Chroma with the raw payload; retry once in case of truncation."],"exampleFix":"# before\nvecs = ef(texts)  # RuntimeError: Unexpected error ... Expecting value: line 1 column 1 (char 0)\n\n# after: distinguish parse failures from API errors\ntry:\n    vecs = ef(texts)\nexcept RuntimeError as e:\n    msg = str(e)\n    if msg.startswith(\"Unexpected error\"):\n        # log one raw request/response pair, then fail loudly\n        raise RuntimeError(f\"Unparseable /embed_sparse response: {msg}\") from e\n    raise","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    vecs = ef(texts)\nexcept RuntimeError as e:\n    if str(e).startswith(\"Unexpected error\"):\n        # underlying cause is appended after the colon (JSONDecodeError, KeyError, ...)\n        logger.exception(\"Unparseable /embed_sparse response: %s\", e)\n        vecs = ef(texts)  # at most one retry for truncated bodies\n    else:\n        raise","preventionTips":["Log the full message — it preserves the original exception text after the prefix.","Keep proxies from rewriting API responses (verify with a manual curl of the same payload).","Pin your chromadb version so client/server contract changes surface in upgrades, not randomly."],"tags":["chroma-cloud","splade","catch-all","json-parse","sparse-embeddings"],"backgroundTag":"api-error-response","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}