chroma-core/chroma · error · ValueError
Limit offset must be non-negative, got {offset}
Error message
Limit offset must be non-negative, got {offset} What it means
Limit.from_dict rejects negative offsets with ValueError: an offset counts records to skip from the start, so any value below 0 is meaningless. The check is offset < 0, run after the int type check, so only integers can reach it.
Source
Thrown at chromadb/execution/expression/operator.py:575
@staticmethod
def from_dict(data: Dict[str, Any]) -> "Limit":
"""Create Limit from dictionary.
Examples:
- {"offset": 10} -> Limit(offset=10)
- {"offset": 10, "limit": 20} -> Limit(offset=10, limit=20)
- {"limit": 20} -> Limit(offset=0, limit=20)
"""
if not isinstance(data, dict):
raise TypeError(f"Expected dict for Limit, got {type(data).__name__}")
offset = data.get("offset", 0)
if not isinstance(offset, int):
raise TypeError(
f"Limit offset must be an integer, got {type(offset).__name__}"
)
if offset < 0:
raise ValueError(f"Limit offset must be non-negative, got {offset}")
limit = data.get("limit")
if limit is not None:
if not isinstance(limit, int):
raise TypeError(
f"Limit limit must be an integer, got {type(limit).__name__}"
)
if limit <= 0:
raise ValueError(f"Limit limit must be positive, got {limit}")
# Check for unexpected keys
allowed_keys = {"offset", "limit"}
unexpected_keys = set(data.keys()) - allowed_keys
if unexpected_keys:
raise ValueError(f"Unexpected keys in Limit dict: {unexpected_keys}")
return Limit(offset=offset, limit=limit)
View on GitHub (pinned to aecdd12c8a)
Solutions
- Clamp the computed offset: offset = max(0, (page - 1) * page_size).
- Treat page 0 and page 1 the same: page = max(page, 1).
- Validate user-supplied page/offset params at the API edge before building the Search payload.
Example fix
# before
offset = (page - 1) * page_size # page=0 -> -10 -> ValueError
Search(limit={'offset': offset, 'limit': page_size})
# after
offset = max(0, (page - 1) * page_size)
Search(limit={'offset': offset, 'limit': page_size}) Defensive patterns
Strategy: validation
Validate before calling
def safe_offset(page: int, page_size: int) -> int:
return max(0, (max(page, 1) - 1) * page_size) Try / catch
try:
Search(limit=limit_cfg)
except ValueError as e:
if 'offset' in str(e):
limit_cfg = {**limit_cfg, 'offset': 0} # or return 400 to the client
else:
raise Prevention
- Never trust client-supplied page numbers; clamp before computing offsets.
- Add a boundary test for page=0 and page=1.
- Log the offending offset together with the failing payload for quick diagnosis.
When it happens
Trigger: Limit.from_dict({'offset': -1}); page arithmetic going below zero, e.g. {'offset': (page - 1) * page_size} with page=0; cursor logic like total - fetched when fetched > total.
Common situations: 1-based page counters fed into a 0-based formula; clients sending page=0 to an API that computes offset=(page-1)*size; paging state carried between requests and underflowing on the short last page.
Related errors
- Limit offset must be an integer, got {type(offset).__name__}
- Limit limit must be positive, got {limit}
- Unexpected keys in Limit dict: {unexpected_keys}
- Expected dict for Limit, got {type(data).__name__}
- Limit limit must be an integer, got {type(limit).__name__}
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/a284a5f83eb0c438.
Report an issue: GitHub.