chroma-core/chroma · error · ValueError

conditional transaction has no collection scope

Error message

conditional transaction has no collection scope

What it means

Raised by ConditionalHttpTransaction._require_scope (chromadb/api/conditional_http.py:233) when a scope-requiring step (recording a get result or building the commit payload) runs on a transaction that never bound itself to a collection. The scope is a frozen (collection_id, tenant, database) tuple recorded on the first prepare_get/buffer_* call; every later step must reuse it. In practice this is a defensive invariant: a transaction with buffered operations always has a scope, so hitting it usually means the transaction lifecycle was manipulated directly or a client bug is present.

Source

Thrown at chromadb/api/conditional_http.py:233

        self._closed = True

    def _ensure_open(self) -> None:
        if self._closed:
            raise ValueError("conditional transaction is closed")

    def _record_scope(
        self, collection_id: UUID, tenant: str, database: str
    ) -> ConditionalHttpScope:
        scope = ConditionalHttpScope(str(collection_id), tenant, database)
        if self._scope is None:
            self._scope = scope
        elif self._scope != scope:
            raise ValueError("conditional transaction cannot span collections")
        return scope

    def _require_scope(self) -> ConditionalHttpScope:
        if self._scope is None:
            raise ValueError("conditional transaction has no collection scope")
        return self._scope

    def _validate_get_request(self, request_payload: ConditionalHttpGetPayload) -> None:
        ids = request_payload.get("ids")
        if ids is not None:
            for id in ids:
                if id in self._buffered_write_ids:
                    raise _invalid_read_after_write(id)
            return

        limit = request_payload.get("limit")
        if not isinstance(limit, int) or limit <= 0:
            raise InvalidArgumentError(
                "transactional filter reads require a positive limit"
            )

    def _validate_read_token(
        self, expected_read_token: Optional[int], actual_read_token: Optional[int]

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Start every transaction with at least one scoped operation (a get or a buffered write) before requesting the commit payload
  2. Do not construct or drive ConditionalHttpTransaction yourself; obtain it from the HTTP client's transaction API so scope is always recorded first
  3. If you only reached this via the public client API, upgrade chromadb to a consistent version and report the reproduction

Example fix

# before
txn = ConditionalHttpTransaction()
payload = txn.prepare_commit_payload()  # no operation ever recorded
# after
collection.get(ids=["doc1"])            # first read records the scope
collection.add(ids=["doc2"], embeddings=[emb])
txn.prepare_commit_payload()             # scope now present
Defensive patterns

Strategy: validation

Validate before calling

from chromadb.api.conditional_http import ConditionalHttpTransaction

def safe_commit(txn):
    # a transaction with any buffered operation always has a scope;
    # commit only after at least one read/write against a collection
    if not txn._operations:  # nothing buffered: commit is a no-op
        txn.close()
        return None
    return txn.prepare_commit_payload()

Try / catch

try:
    txn.prepare_commit_payload()
except ValueError as e:
    if "no collection scope" in str(e):
        # transaction was misused: restart it and perform a read/write first
        ...
    raise

Prevention

When it happens

Trigger: Calling prepare_commit_payload() or record_get() on a ConditionalHttpTransaction instance that never received a prepare_get/buffer_add/buffer_update/buffer_upsert/buffer_delete call for any collection. Not reachable through the normal client flow where the first read/write precedes the commit.

Common situations: Test code or custom wrappers that construct ConditionalHttpTransaction() manually and commit without operations; reusing or resetting transaction internals; a chromadb version mismatch between the client wrapper and this module after a partial upgrade.

Related errors


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