chroma-core/chroma · error · TypeError
Expected dict for Limit, got {type(data).__name__}
Error message
Expected dict for Limit, got {type(data).__name__} What it means
Limit.from_dict deserializes a pagination spec and only accepts a Python dict with 'offset'/'limit' keys. This TypeError is the first guard: any non-dict (list, str, int, None, tuple) is rejected before field validation runs. It is reached from Search(limit={...}) (chromadb/execution/expression/plan.py:138) and from code that round-trips a serialized Search payload.
Source
Thrown at chromadb/execution/expression/operator.py:567
def to_dict(self) -> Dict[str, Any]:
"""Convert the Limit to a dictionary for JSON serialization"""
result = {"offset": self.offset}
if self.limit is not None:
result["limit"] = self.limit
return result
@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}")
View on GitHub (pinned to aecdd12c8a)
Solutions
- Pass the value to Search() instead - Search(limit=20) accepts an int and builds Limit.from_dict({'limit': 20, 'offset': 0}) for you (plan.py:135-136).
- Wrap scalars before calling from_dict: Limit.from_dict({'limit': value}).
- If the input comes from JSON/YAML, check isinstance(data, dict) first and return a clear 400-style error to the caller.
Example fix
# before
Limit.from_dict(cfg['limit']) # cfg['limit'] == 20 -> TypeError
# after
Search(limit=cfg['limit']) # int handled by Search
# or
Limit.from_dict({'limit': cfg['limit']}) Defensive patterns
Strategy: type-guard
Validate before calling
def as_limit_dict(data):
'''Coerce common shapes into a Limit.from_dict-compatible dict.'''
if isinstance(data, bool):
raise TypeError('bool is not a valid limit payload')
if isinstance(data, int):
return {'limit': data}
if not isinstance(data, dict):
raise TypeError(f'limit payload must be a dict or int, got {type(data).__name__}')
return data
Search(limit=as_limit_dict(cfg['limit'])) Type guard
def is_limit_payload(data) -> bool:
return isinstance(data, dict) and set(data) <= {'offset', 'limit'} Try / catch
try:
limit = Limit.from_dict(raw)
except TypeError as e:
raise ValueError(f'invalid limit payload: {e}') from e Prevention
- Build payloads through Search(limit=...) or the Limit dataclass instead of calling from_dict on raw values.
- Validate the shape of externally loaded JSON before passing it to from_dict.
- Check payloads at the API boundary so bad limit shapes fail with your own error message.
When it happens
Trigger: Calling Limit.from_dict(20), Limit.from_dict('20'), or Limit.from_dict([10, 20]) directly; feeding a JSON-decoded value whose limit member is a bare scalar or array; deserializing a stored Search payload where the limit field lost its object shape.
Common situations: Porting from the classic collection.query(n_results=10) API and feeding the int into Limit.from_dict; YAML/JSON configs storing limit as a scalar or list; generic parse-then-build pipelines that assume from_dict accepts ints because Search(limit=...) does.
Related errors
- Limit limit must be an integer, got {type(limit).__name__}
- Limit offset must be an integer, got {type(offset).__name__}
- Limit limit must be positive, got {limit}
- Multiple embedding functions provided. Please provide only o
- Unauthorized
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/9451f6659a92c93b.
Report an issue: GitHub.