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
- Pass an explicit positive integer limit on every filter-based get inside the transaction
- Or switch the read to id-based form (ids=[...]) which needs no limit
- 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
- Default every transactional filter read to a positive limit (e.g. 100)
- Prefer id-based gets inside transactions when you know the ids
- Wrap limit arithmetic so it can never produce 0 or None
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
- transaction already has a buffered write for id "{id}"
- 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
- conditional transaction has no collection scope
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/a15f8c3ce39addf9.
Report an issue: GitHub.