chroma-core/chroma · error · InvalidArgumentError
transaction already has a buffered write for id "{id}"
Error message
transaction already has a buffered write for id "{id}" What it means
Raised by _validate_buffered_write (chromadb/api/conditional_http.py:292) when an id is buffered for write a second time by a later call within the same transaction. Unlike the per-call duplicate check, this spans the whole transaction via _buffered_write_ids: once a write for an id is pending, any further write to that id (even in a separate call) is rejected, because the commit applies buffered operations in order and a second payload would make the final state ambiguous against the OCC read set.
Source
Thrown at chromadb/api/conditional_http.py:292
operation: str,
ids: IDs,
payload: ConditionalHttpJsonPayload,
) -> None:
self._validate_buffered_write(operation, ids)
for id in ids:
self._buffered_write_ids.add(id)
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 'View on GitHub (pinned to aecdd12c8a)
Solutions
- Restructure so each id is written exactly once per transaction: decide the final operation (add, update, upsert, or delete) before buffering it
- Batch same-id writes into a single call with the final payload (upsert is usually what you want)
- Track written ids client-side in a set as you go and skip or consolidate repeats
Example fix
# before
with client.transaction():
collection.update(ids=["a"], metadatas=[{"v": 1}])
collection.delete(ids=["a"]) # same id buffered twice
# after
with client.transaction():
collection.delete(ids=["a"]) # single final operation for "a" Defensive patterns
Strategy: validation
Validate before calling
written = set()
def txn_write_once(ids):
dupes = written.intersection(ids)
if dupes:
raise RuntimeError(f"ids already buffered in this transaction: {sorted(dupes)}")
written.update(ids)
return ids Prevention
- Track every id you have written in the current transaction in a client-side set
- Consolidate same-id writes into one final operation before buffering
- Do not retry a buffered write inside the same transaction; abort and start a new one
When it happens
Trigger: Two transactional writes touching the same id in one transaction: collection.update(ids=["a"], ...) followed later by collection.delete(ids=["a"], ...), or two add/upsert calls sharing an id across different code paths inside one transaction block.
Common situations: A retry loop inside the transaction that re-buffers a failed write; helper functions each doing their own upsert for the same record, composed in one transaction; processing a list where logic updates a record, then a later branch deletes it.
Related errors
- transactional write request contains duplicate id "{id}"
- transactional filter reads require a positive limit
- transactional add for id "{id}" requires a prior read provin
- transactional update for id "{id}" requires a prior read pro
- transactional delete for id "{id}" requires a prior read pro
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/e70170a27a1be6d3.
Report an issue: GitHub.