chroma-core/chroma · error · InvalidArgumentError

transactional filter reads require a positive limit

Error message

transactional filter reads require a positive limit

What it means

Raised by _validate_get_request (chromadb/api/conditional_http.py:246) when a read inside a conditional HTTP transaction supplies neither ids nor a positive integer limit. Transactional (OCC) reads must have an enumerable read set: id-based reads are bounded by construction, so filter-based reads (where/where_document) must be explicitly bounded with limit so the server can tie the read token to a finite set of records. A missing, zero, negative, or non-int limit (e.g. None, the default for a plain get) is rejected.

Source

Thrown at chromadb/api/conditional_http.py:246

            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]
    ) -> None:
        if actual_read_token is None:
            raise InternalError(
                "transactional get response did not include an OCC read token"
            )
        if actual_read_token > _MAX_I64:
            raise InternalError(
                f"transactional read token offset {actual_read_token} exceeds i64 range"
            )
        if expected_read_token is not None and expected_read_token != actual_read_token:
            raise InternalError(
                "transactional read token changed from log upper bound offset "
                f"{expected_read_token} to {actual_read_token}"

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Pass an explicit positive integer limit on every filter-based get inside the transaction
  2. Or switch the read to id-based form (ids=[...]) which needs no limit
  3. If you truly need all matching records, page through with limit + offset while staying inside the transaction

Example fix

# before
with client.transaction() as txn:
    rows = collection.get(where={"kind": "doc"})  # limit=None -> error
# after
with client.transaction() as txn:
    rows = collection.get(where={"kind": "doc"}, limit=100)
Defensive patterns

Strategy: validation

Validate before calling

def validate_txn_get(payload: dict) -> None:
    if payload.get("ids") is None:
        limit = payload.get("limit")
        assert isinstance(limit, int) and not isinstance(limit, bool) and limit > 0, \
            "transactional filter reads need ids or a positive int limit"

Try / catch

from chromadb.errors import InvalidArgumentError

try:
    rows = collection.get(where=f, limit=limit)
except InvalidArgumentError as e:
    if "positive limit" in str(e):
        rows = collection.get(where=f, limit=100)  # bounded retry
    else:
        raise

Prevention

When it happens

Trigger: Inside a transaction, calling collection.get(where=..., where_document=..., limit=None) or limit=0/negative/string; any transactional get whose payload has ids=None and a limit that is not a positive int. Plain collection.get() with no arguments inside a transaction hits this because limit defaults to None.

Common situations: Copying non-transactional code that used unbounded get() into a transactional block; paginating with a limit computed from arithmetic that can yield 0; passing limit as a string from config or env vars.

Related errors


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