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

  1. Restructure so each id is written exactly once per transaction: decide the final operation (add, update, upsert, or delete) before buffering it
  2. Batch same-id writes into a single call with the final payload (upsert is usually what you want)
  3. 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

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


AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16). Data as JSON: /api/errors/e70170a27a1be6d3. Report an issue: GitHub.