chroma-core/chroma · error · ChromaServerError

${response.status}: ${response.statusText}

Error message

${response.status}: ${response.statusText}

What it means

Thrown by chromaFetch (chroma-fetch.ts:142) as a ChromaServerError for any non-OK status not handled by the 400/401/403/404/409/412/422/429 switch — in practice HTTP 5xx. The message comes from getErrorMessage(): the body's message or error field if present, else the raw `${status}: ${statusText}` fallback, which is what you see when the error body is empty or not JSON (e.g. a 502/504 HTML page from a proxy).

Source

Thrown at clients/new-js/packages/chromadb/src/chroma-fetch.ts:142

        ) {
          throw error;
        }
        throw new ChromaClientError(
          `Unprocessable Entity: ${response.statusText}`,
        );
      }
    case 429:
      const rateLimitBody = await getErrorBody(response);
      if (rateLimitBody.error === "Backoff") {
        throw new ChromaBackoffError(
          rateLimitBody.message || "Backoff and retry",
        );
      }
      throw new ChromaRateLimitError("Rate limit exceeded");
  }

  const errorMessage = await getErrorMessage(response);
  throw new ChromaServerError(errorMessage);
};

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Check Chroma server health/logs (docker logs, pod events) for the root cause of the 5xx.
  2. Retry with exponential backoff — 5xx and gateway errors are usually transient, especially 502/503/504.
  3. If '504'-style timeouts repeat under load, reduce batch sizes or scale the server (more replicas/CPU/memory).
  4. Verify client/server version compatibility if a deterministic 500 occurs on a specific call.

Example fix

// before
await collection.query({ queryTexts: ["x"] }); // occasional 502/504 from gateway

// after
async function withRetry<T>(fn: () => Promise<T>, tries = 5): Promise<T> {
  for (let i = 0; ; i++) {
    try { return await fn(); }
    catch (e) {
      if (e instanceof ChromaServerError && i < tries - 1) {
        await new Promise(r => setTimeout(r, 2 ** i * 250 + Math.random() * 250));
        continue;
      }
      throw e;
    }
  }
}
await withRetry(() => collection.query({ queryTexts: ["x"] }));
Defensive patterns

Strategy: retry

Validate before calling

async function healthy(url: string): Promise<boolean> {
  try { return (await fetch(`${url}/api/v2/heartbeat`)).ok; } catch { return false; }
}

Try / catch

for (let attempt = 0; ; attempt++) {
  try {
    return await operation();
  } catch (e) {
    const transient = e instanceof ChromaServerError && !/\b5[0-9]{2}\b.*[Pp]anic/.test(e.message);
    if (transient && attempt < 5) {
      await new Promise(r => setTimeout(r, 2 ** attempt * 250 + Math.random() * 250));
      continue;
    }
    throw e;
  }
}

Prevention

When it happens

Trigger: Chroma server crashes (500), unhandled server bugs, maintenance restarts, or infrastructure-layer 502/503/504 from load balancers and proxies in front of Chroma when the upstream is down or timing out.

Common situations: Long ingestion jobs hitting a server OOM/restart; Kubernetes pod recycling while clients are connected; nginx returning '504: Gateway Time-out' when chroma is overloaded; version-skew server panics on new payloads.

Related errors


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