chroma-core/chroma · error · ChromaClientError

Precondition Failed

Error message

Precondition Failed

What it means

Thrown by chromaFetch (chroma-fetch.ts:105) as a generic ChromaClientError when the server returns 412 but the body is not a StaleReadError. HTTP 412 means a precondition the client asserted in request headers (e.g. If-Match / version-match style checks) failed: the resource state does not satisfy the condition the client demanded.

Source

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

      if (
        conflictBody.error === "ConditionalWriteConflictError" ||
        conflictBody.message === "conditional write conflict"
      ) {
        throw new ChromaConditionalWriteConflictError(
          conflictBody.message || "conditional write conflict",
        );
      }
      throw new ChromaUniqueError(
        conflictBody.message || "The resource already exists",
      );
    case 412:
      const preconditionBody = await getErrorBody(response);
      if (preconditionBody.error === "StaleReadError") {
        throw new ChromaStaleReadError(
          preconditionBody.message || "stale read",
        );
      }
      throw new ChromaClientError(
        preconditionBody.message || "Precondition Failed",
      );
    case 422:
      try {
        const body = await response.json();
        if (
          body &&
          body.message &&
          (body.message.startsWith("Quota exceeded") ||
            body.message.startsWith("Billing limit exceeded"))
        ) {
          throw new ChromaQuotaExceededError(body?.message);
        }
        throw new ChromaClientError(body?.message || "Unprocessable Entity");
      } catch (error) {
        if (
          error instanceof ChromaQuotaExceededError ||
          error instanceof ChromaClientError

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Inspect the server's message in the error body to identify which precondition failed.
  2. Re-read the current resource state/version and reissue the request with a fresh precondition or none.
  3. If a proxy injects precondition headers, remove or fix that configuration.
  4. Wrap the call in a retry loop that refreshes the version on each 412.

Example fix

// before
await collection.delete({ ids }, /* ifVersion */ staleVersion); // 412 Precondition Failed

// after
const current = await client.getCollection({ name: collection.name }); // refresh version
await current.delete({ ids }); // or pass current.version as the precondition
Defensive patterns

Strategy: retry

Try / catch

try {
  await collection.delete(args);
} catch (e) {
  if (e instanceof ChromaClientError && /Precondition/.test(e.message)) {
    // re-read current version, then re-issue with fresh precondition or without one
  }
  throw e;
}

Prevention

When it happens

Trigger: A request with a version/precondition header whose expectation no longer holds — e.g. delete or update with if-version equal to an outdated collection version, or gateway-injected precondition checks failing.

Common situations: Optimistic version checks on collection modifications racing with other writers; proxies/load balancers adding If-* header checks; custom server middleware enforcing preconditions.

Related errors


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