chroma-core/chroma · warning · ChromaStaleReadError
stale read
Error message
stale read
What it means
Thrown by chromaFetch (chroma-fetch.ts:101) as a ChromaStaleReadError when the server returns 412 and the body identifies a StaleReadError. It comes from Chroma's consistency controls: the read was issued with a session/consistency token older than what the server requires, so the server refuses to serve data that might violate the requested consistency level and asks the client to retry on a newer session.
Source
Thrown at clients/new-js/packages/chromadb/src/chroma-fetch.ts:101
`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 {
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");View on GitHub (pinned to aecdd12c8a)
Solutions
- Catch ChromaStaleReadError and retry the read after refreshing the session/token (re-obtain the collection handle or session from the server).
- Avoid caching session tokens across long idle periods; refresh them before read-after-write sequences.
- If strict consistency is not needed, perform the read without the session/consistency parameter.
Example fix
// before
const col = await client.getCollection({ name: "docs" }); // session token captured
await new Promise(r => setTimeout(r, 60000));
await col.query({ queryTexts: ["x"] }); // 412 StaleReadError if session advanced
// after
try {
await col.query({ queryTexts: ["x"] });
} catch (e) {
if (e instanceof ChromaStaleReadError) {
const fresh = await client.getCollection({ name: "docs" });
return fresh.query({ queryTexts: ["x"] });
}
throw e;
} Defensive patterns
Strategy: retry
Try / catch
try {
return await collection.query(args);
} catch (e) {
if (e instanceof ChromaStaleReadError) {
const fresh = await client.getCollection({ name: collection.name });
return fresh.query(args); // session refreshed by re-fetch
}
throw e;
} Prevention
- Refresh session-scoped handles before read-after-write sequences.
- Do not cache session tokens across long idle periods.
- Retry once on stale read before escalating — it is an expected consistency signal, not a bug.
When it happens
Trigger: Reads (get/query/count) sent with a previously obtained session token after the session advanced server-side; using a session-scoped client across a long idle period; explicitly requesting strong consistency with a stale token.
Common situations: Caching a session-scoped collection handle too long; pauses between write and read where the session expires; retrying an old request payload after newer writes have bumped the session.
Related errors
- conditional write conflict
- Precondition Failed
- Backoff and retry
- Rate limit exceeded
- ${response.status}: ${response.statusText}
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/d27a6105fcabf3dc.
Report an issue: GitHub.