{"record":{"id":"d27a6105fcabf3dc","repo":"chroma-core/chroma","slug":"stale-read","errorCode":null,"errorMessage":"stale read","messagePattern":"stale read","errorType":"http","errorClass":"ChromaStaleReadError","httpStatus":412,"severity":"warning","filePath":"clients/new-js/packages/chromadb/src/chroma-fetch.ts","lineNumber":101,"sourceCode":"        `The requested resource could not be found`,\n      );\n    case 409:\n      const conflictBody = await getErrorBody(response);\n      if (\n        conflictBody.error === \"ConditionalWriteConflictError\" ||\n        conflictBody.message === \"conditional write conflict\"\n      ) {\n        throw new ChromaConditionalWriteConflictError(\n          conflictBody.message || \"conditional write conflict\",\n        );\n      }\n      throw new ChromaUniqueError(\n        conflictBody.message || \"The resource already exists\",\n      );\n    case 412:\n      const preconditionBody = await getErrorBody(response);\n      if (preconditionBody.error === \"StaleReadError\") {\n        throw new ChromaStaleReadError(\n          preconditionBody.message || \"stale read\",\n        );\n      }\n      throw new ChromaClientError(\n        preconditionBody.message || \"Precondition Failed\",\n      );\n    case 422:\n      try {\n        const body = await response.json();\n        if (\n          body &&\n          body.message &&\n          (body.message.startsWith(\"Quota exceeded\") ||\n            body.message.startsWith(\"Billing limit exceeded\"))\n        ) {\n          throw new ChromaQuotaExceededError(body?.message);\n        }\n        throw new ChromaClientError(body?.message || \"Unprocessable Entity\");","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/clients/new-js/packages/chromadb/src/chroma-fetch.ts#L83-L119","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst col = await client.getCollection({ name: \"docs\" }); // session token captured\nawait new Promise(r => setTimeout(r, 60000));\nawait col.query({ queryTexts: [\"x\"] }); // 412 StaleReadError if session advanced\n\n// after\ntry {\n  await col.query({ queryTexts: [\"x\"] });\n} catch (e) {\n  if (e instanceof ChromaStaleReadError) {\n    const fresh = await client.getCollection({ name: \"docs\" });\n    return fresh.query({ queryTexts: [\"x\"] });\n  }\n  throw e;\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  return await collection.query(args);\n} catch (e) {\n  if (e instanceof ChromaStaleReadError) {\n    const fresh = await client.getCollection({ name: collection.name });\n    return fresh.query(args); // session refreshed by re-fetch\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["http-412","consistency","session","retryable"],"backgroundTag":"stale-session-token","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}