chroma-core/chroma · warning · ChromaConditionalWriteConflictError
conditional write conflict
Error message
conditional write conflict
What it means
Thrown by chromaFetch (chroma-fetch.ts:91) as a ChromaConditionalWriteConflictError when the server returns 409 and the body identifies a ConditionalWriteConflictError. This is Chroma's optimistic-concurrency control: a write (add/upsert/update/delete) whose version precondition did not match the collection's current version lost the race against a concurrent writer, and the server rejected it so you can retry against the new state.
Source
Thrown at clients/new-js/packages/chromadb/src/chroma-fetch.ts:91
} with status: ${status}`,
);
case 401:
throw new ChromaUnauthorizedError(`Unauthorized`);
case 403:
throw new ChromaForbiddenError(
`You do not have permission to access the requested resource.`,
);
case 404:
throw new ChromaNotFoundError(
`The requested resource could not be found`,
);
case 409:
const conflictBody = await getErrorBody(response);
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 {View on GitHub (pinned to aecdd12c8a)
Solutions
- Catch ChromaConditionalWriteConflictError and retry the operation after re-reading the current collection version, ideally with jittered backoff.
- Reduce write contention by funnelting writes through a single writer/queue for the hot collection.
- Re-fetch the collection handle (to refresh its version) before each conditional write in long sessions.
- If you do not need OCC guarantees, drop the version precondition parameter.
Example fix
// before
await collection.upsert({ ids, documents, /* version: staleVersion */ }); // 409 conditional write conflict
// after
try {
await collection.upsert({ ids, documents });
} catch (e) {
if (e instanceof ChromaConditionalWriteConflictError) {
await sleep(50 * (1 + Math.random()));
return collection.upsert({ ids, documents }); // retry against fresh state
}
throw e;
} Defensive patterns
Strategy: retry
Try / catch
for (let attempt = 0; ; attempt++) {
try {
return await collection.upsert(payload);
} catch (e) {
if (e instanceof ChromaConditionalWriteConflictError && attempt < 5) {
await new Promise(r => setTimeout(r, 2 ** attempt * 50 + Math.random() * 100));
continue; // optionally refresh collection version here
}
throw e;
}
} Prevention
- Re-fetch the collection version right before conditional writes in concurrent pipelines.
- Serialize writers per collection (queue) when contention is high.
- Treat this error as retryable by design — never surface it as a hard failure without one retry.
When it happens
Trigger: Two concurrent writers mutating the same collection with version precondition headers (e.g. upsert with if-collection-version); long-running read-then-write sequences where the collection changed in between; high-concurrency ingestion pipelines using conditional writes.
Common situations: Parallel batch writers to one collection; retries after timeouts that actually succeeded server-side; cache of collection version kept too long before a conditional update.
Related errors
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/394edf3f528d0d0b.
Report an issue: GitHub.