chroma-core/chroma · error · InvalidArgumentError
transactional delete for id "{id}" requires a prior read pro
Error message
transactional delete for id "{id}" requires a prior read proving the id is present What it means
Raised by _validate_write_precondition (chromadb/api/conditional_http.py:309) when a transactional delete targets an id the transaction has not proven present. Like add and update, delete follows the read-then-write protocol: only ids returned by a prior get inside the same transaction land in _known_present, and deleting an unobserved id is rejected. This makes deletes conflict-detectable via the OCC read token at commit time instead of silently no-oping.
Source
Thrown at chromadb/api/conditional_http.py:309
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:
if not isinstance(transaction, ConditionalHttpTransaction):
raise ValueError("invalid conditional transaction for HTTP client")
return transaction
def _invalid_read_after_write(id: str) -> InvalidArgumentError:
return InvalidArgumentError(
f'cannot transactionally read id "{id}" after buffering a write for it'
)
View on GitHub (pinned to aecdd12c8a)
Solutions
- Read the ids with an id-based get inside the same transaction, then delete only the ids that came back
- Filter your id list against the get result before calling delete
- Delete unobserved ids outside the transaction, or accept that transactional deletes require the read by design
Example fix
# before
with client.transaction():
collection.delete(ids=["gone", "here"])
# after
with client.transaction():
got = collection.get(ids=["gone", "here"])
present = got["ids"]
if present:
collection.delete(ids=present) Defensive patterns
Strategy: validation
Validate before calling
def txn_delete(collection, ids):
got = collection.get(ids=ids) # proves presence inside the txn
present = list(got["ids"])
if present:
collection.delete(ids=present)
return set(ids) - set(present) # ids that were already absent Try / catch
from chromadb.errors import InvalidArgumentError
try:
collection.delete(ids=ids)
except InvalidArgumentError as e:
if "requires a prior read" in str(e):
got = collection.get(ids=ids)
if got["ids"]:
collection.delete(ids=list(got["ids"]))
else:
raise Prevention
- Intersect your delete list with an id-based get result before deleting
- On conflict-retry, re-read in the new transaction before re-deleting
- Gather ids to delete via a transactional read, not from external state
When it happens
Trigger: collection.delete(ids=["doc1"]) inside a transaction with no prior get returning "doc1"; deleting based on a stale application-side existence check; the earlier get using where filters rather than explicit ids.
Common situations: Cleanup jobs that delete by a list of ids gathered outside the transaction; retrying a delete in a new transaction after a conflict without re-reading; id lists built from another system (CMS, queue) where some ids were already removed.
Related errors
- transactional add for id "{id}" requires a prior read provin
- transactional update 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/87321162957dbfd2.
Report an issue: GitHub.