chroma-core/chroma · error · TypeError

Limit limit must be an integer, got {type(limit).__name__}

Error message

Limit limit must be an integer, got {type(limit).__name__}

What it means

When a 'limit' key is present in the Limit dict it must be a Python int (None is allowed and means no limit). Floats such as 20.0, strings such as '20', and numpy integers (np.int64 is not a subclass of int) all fail isinstance(limit, int) and raise TypeError.

Source

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

        - {"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)


@dataclass
class Projection:
    document: bool = False
    embedding: bool = False

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Pass a plain Python int: {'limit': 20}.
  2. Convert numpy scalars at the boundary: {'limit': int(n)}.
  3. Coerce numeric strings/whole floats once during config parsing: int(value).

Example fix

# before
Search(limit={'limit': np.int64(20)})   # -> TypeError: got int64

# after
Search(limit={'limit': int(n)})
Defensive patterns

Strategy: validation

Validate before calling

def as_int(value):
    if isinstance(value, bool):
        raise TypeError('bool is not a valid limit')
    if isinstance(value, int):
        return value
    if isinstance(value, float) and value.is_integer():
        return int(value)
    if hasattr(value, 'item'):  # numpy scalars
        return int(value.item())
    raise TypeError(f'cannot coerce {type(value).__name__} to int')

Search(limit={'limit': as_int(cfg['limit'])})

Prevention

When it happens

Trigger: Limit.from_dict({'limit': '20'}); {'limit': 20.0} from a strict JSON decoder; {'limit': np.int64(20)} from numpy sizing math.

Common situations: Configs storing limits as strings; numpy arrays/constants feeding pagination sizes; decoders that emit floats for all JSON numbers.

Related errors


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