chroma-core/chroma · error · InvalidArgumentError
transactional add for id "{id}" requires a prior read provin
Error message
transactional add for id "{id}" requires a prior read proving the id is absent What it means
Raised by _validate_write_precondition (chromadb/api/conditional_http.py:299) when a transactional add targets an id the transaction has not proven absent. The conditional transaction protocol is read-then-write: _known_absent is populated only by a prior id-based get (no where/where_document) inside the same transaction that did not return the id. This prevents blind inserts from racing with concurrent writes, since the commit's OCC check is anchored to the read set.
Source
Thrown at chromadb/api/conditional_http.py:299
self._operations.append({"operation": operation, "payload": payload})
def _validate_buffered_write(self, operation: str, ids: IDs) -> None:
call_ids: Set[str] = set()
for id in ids:
if id in call_ids:
raise InvalidArgumentError(
f'transactional write request contains duplicate id "{id}"'
)
call_ids.add(id)
if id in self._buffered_write_ids:
raise InvalidArgumentError(
f'transaction already has a buffered write for id "{id}"'
)
self._validate_write_precondition(operation, id)
def _validate_write_precondition(self, operation: str, id: str) -> None:
if operation == "add" and id not in self._known_absent:
raise InvalidArgumentError(
f'transactional add for id "{id}" requires a prior read '
"proving the id is absent"
)
if operation == "update" and id not in self._known_present:
raise InvalidArgumentError(
f'transactional update for id "{id}" requires a prior read '
"proving the id is present"
)
if operation == "delete" and id not in self._known_present:
raise InvalidArgumentError(
f'transactional delete for id "{id}" requires a prior read '
"proving the id is present"
)
def require_conditional_http_transaction(
transaction: object,
) -> ConditionalHttpTransaction:View on GitHub (pinned to aecdd12c8a)
Solutions
- Inside the same transaction, first do an id-based get (collection.get(ids=[...]) with no where/where_document), then add the ids that were not returned
- If you do not need insert-if-absent semantics, use upsert instead - it has no read precondition
- Ensure the read and the add use the same transaction instance
Example fix
# before
with client.transaction():
collection.add(ids=["doc1"], embeddings=[emb]) # no prior read
# after
with client.transaction():
existing = collection.get(ids=["doc1"]) # proves absence
collection.add(ids=["doc1"], embeddings=[emb]) Defensive patterns
Strategy: validation
Validate before calling
def prove_absent(collection, ids):
got = collection.get(ids=ids) # id-based, no where filters
return [i for i in ids if i not in set(got["ids"])]
absent = prove_absent(collection, new_ids)
# only add() ids proven absent, inside the same transaction Try / catch
from chromadb.errors import InvalidArgumentError
try:
collection.add(ids=["doc1"], embeddings=[emb])
except InvalidArgumentError as e:
if "requires a prior read" in str(e):
collection.get(ids=["doc1"])
collection.add(ids=["doc1"], embeddings=[emb])
else:
raise Prevention
- Read (id-based get, no where) before every transactional add
- If the record may exist, use upsert - it carries no read precondition
- Keep the proving read and the add in the same transaction instance
When it happens
Trigger: Calling collection.add(ids=["doc1"], ...) inside a transaction without a preceding collection.get(ids=["doc1"]) in that same transaction; reading with a where filter first (which never marks ids absent); reading in a different or earlier transaction than the one used for the add.
Common situations: Porting non-transactional code that called add() directly; doing an existence check via get(where=...) or a query, which does not populate _known_absent; splitting read and write across two transaction objects.
Related errors
- transactional update for id "{id}" requires a prior read pro
- transactional delete for id "{id}" requires a prior read pro
- transactional filter reads require a positive limit
- transaction already has a buffered write for id "{id}"
- conditional transaction has no collection scope
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/2507fe9972bd6207.
Report an issue: GitHub.