chroma-core/chroma · error · ValueError

Limit limit must be positive, got {limit}

Error message

Limit limit must be positive, got {limit}

What it means

A Limit with an explicit 'limit' value must be >= 1; 0 and negatives raise ValueError. This is deliberate: limit=None already encodes 'no limit', so 0 is treated as a caller bug rather than a meaningful page of zero results.

Source

Thrown at chromadb/execution/expression/operator.py:584

        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)


@dataclass
class Projection:
    document: bool = False
    embedding: bool = False
    metadata: bool = False
    rank: bool = False
    uri: bool = False

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Send limit=None (or omit the key / use Limit()) when you mean no limit.
  2. Clamp computed sizes to at least 1: max(1, remaining).
  3. Short-circuit '0 results' requests at your API layer instead of building a Search.

Example fix

# before
Search(limit={'limit': max(0, remaining)})   # remaining=0 -> ValueError

# after
limit = None if remaining <= 0 else remaining
Search(limit=limit)
Defensive patterns

Strategy: validation

Validate before calling

def page_limit(requested):
    if requested is None or requested <= 0:
        return None          # no limit
    return requested

Search(limit=page_limit(cfg.get('limit')))

Prevention

When it happens

Trigger: Limit.from_dict({'limit': 0}); {'limit': -5}; computed sizes flooring to zero, e.g. {'limit': max(0, remaining)} when nothing remains.

Common situations: Clamping code producing 0; defaulting a missing config to 0 instead of None; UI 'show 0 rows' options forwarded verbatim to the query layer.

Related errors


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