chroma-core/chroma · error · RuntimeError

Unknown error

Error message

Unknown error

What it means

_convert_resp expects a JSON body containing a 'data' array from the Jina API; when 'data' is absent it raises RuntimeError with the body's 'detail' field, falling back to the literal 'Unknown error' when the body has neither key. This means the HTTP call completed but returned an error/ malformed payload (auth failure, invalid model, rate limit, HTML error page parsed as JSON) that did not follow the expected error schema. It is the catch-all for any non-success response shape Jina returns.

Source

Thrown at chromadb/utils/embedding_functions/jina_embedding_function.py:171

        # overwrite parameteres when query payload is used
        if is_query and self.query_config is not None:
            for key, value in self.query_config.items():
                payload[key] = value

        return payload

    def _convert_resp(self, resp: Any, is_query: bool = False) -> Embeddings:
        """
        Convert the response from the Jina AI API to a list of numpy arrays.

        Args:
            resp (Any): The response from the Jina AI API.

        Returns:
            Embeddings: A list of numpy arrays representing the embeddings.
        """
        if "data" not in resp:
            raise RuntimeError(resp.get("detail", "Unknown error"))

        embeddings_data: List[Dict[str, Union[int, List[float]]]] = resp["data"]

        # Sort resulting embeddings by index
        sorted_embeddings = sorted(embeddings_data, key=lambda e: e["index"])

        # Return embeddings as numpy arrays
        return [
            np.array(result["embedding"], dtype=np.float32)
            for result in sorted_embeddings
        ]

    def __call__(self, input: Embeddable) -> Embeddings:
        """
        Get the embeddings for a list of texts.

        Args:
            input (Embeddable): A list of texts and/or images to get embeddings for.

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Catch RuntimeError around add/query and log the full response body to identify the real cause
  2. Verify the API key works: curl -H "Authorization: Bearer $JINA_API_KEY" https://api.jina.ai/v1/embeddings -d '{"model":"jina-embeddings-v3","input":["test"]}'
  3. Confirm model_name is a currently served Jina model (jina-embeddings-v3/v4, jina-clip-v1/v2)
  4. Add backoff/retry for transient 429/5xx and reduce batch sizes

Example fix

# before
vectors = ef(["hello world"])  # RuntimeError: Unknown error, no diagnostics

# after
from tenacity import retry, wait_exponential, stop_after_attempt
@retry(wait=wait_exponential(multiplier=1, max=10), stop=stop_after_attempt(3),
       retry_error_callback=lambda s: (_ for _ in ()).throw(RuntimeError("Jina API failed after retries")))
def embed(texts):
    try:
        return ef(texts)
    except RuntimeError as e:
        print("Jina error body:", e.args[0])  # inspect real payload
        raise
Defensive patterns

Strategy: try-catch

Validate before calling

import httpx, os

def jina_healthcheck() -> None:
    r = httpx.post(
        "https://api.jina.ai/v1/embeddings",
        headers={"Authorization": f"Bearer {os.environ['JINA_API_KEY']}"},
        json={"model": "jina-embeddings-v3", "input": ["ping"]},
        timeout=10,
    )
    if "data" not in r.json():
        raise RuntimeError(f"Jina API unhealthy: {r.status_code} {r.text[:200]}")

jina_healthcheck()
collection.add(documents=docs, ids=ids)

Try / catch

import logging

log = logging.getLogger(__name__)
try:
    vectors = ef(texts)
except RuntimeError as e:
    detail = e.args[0] if e.args else ""
    if "data" not in str(detail):
        log.error("Jina API error payload: %s", detail)
        raise RuntimeError(f"Jina embeddings call failed: {detail!r}") from e
    raise

Prevention

When it happens

Trigger: Invalid or revoked API key returning a body without 'detail'; wrong model_name (e.g. retired model); 429 rate-limit or 5xx gateway bodies; a proxy/CDN (e.g. a captive portal) returning JSON without 'data'; triggered on any add/query since __call__ and embed_query both pass through _convert_resp.

Common situations: Expired Jina API keys; hitting free-tier rate limits in batch ingestion; regional API incidents; corporate proxies rewriting responses.

Related errors


AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16). Data as JSON: /api/errors/1f8077594c214f07. Report an issue: GitHub.