{"record":{"id":"9451f6659a92c93b","repo":"chroma-core/chroma","slug":"expected-dict-for-limit-got-type-data-name","errorCode":null,"errorMessage":"Expected dict for Limit, got {type(data).__name__}","messagePattern":"Expected dict for Limit, got (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"chromadb/execution/expression/operator.py","lineNumber":567,"sourceCode":"\n    def to_dict(self) -> Dict[str, Any]:\n        \"\"\"Convert the Limit to a dictionary for JSON serialization\"\"\"\n        result = {\"offset\": self.offset}\n        if self.limit is not None:\n            result[\"limit\"] = self.limit\n        return result\n\n    @staticmethod\n    def from_dict(data: Dict[str, Any]) -> \"Limit\":\n        \"\"\"Create Limit from dictionary.\n\n        Examples:\n        - {\"offset\": 10} -> Limit(offset=10)\n        - {\"offset\": 10, \"limit\": 20} -> Limit(offset=10, limit=20)\n        - {\"limit\": 20} -> Limit(offset=0, limit=20)\n        \"\"\"\n        if not isinstance(data, dict):\n            raise TypeError(f\"Expected dict for Limit, got {type(data).__name__}\")\n\n        offset = data.get(\"offset\", 0)\n        if not isinstance(offset, int):\n            raise TypeError(\n                f\"Limit offset must be an integer, got {type(offset).__name__}\"\n            )\n        if offset < 0:\n            raise ValueError(f\"Limit offset must be non-negative, got {offset}\")\n\n        limit = data.get(\"limit\")\n        if limit is not None:\n            if not isinstance(limit, int):\n                raise TypeError(\n                    f\"Limit limit must be an integer, got {type(limit).__name__}\"\n                )\n            if limit <= 0:\n                raise ValueError(f\"Limit limit must be positive, got {limit}\")\n","sourceCodeStart":549,"sourceCodeEnd":585,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/chromadb/execution/expression/operator.py#L549-L585","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\nLimit.from_dict(cfg['limit'])          # cfg['limit'] == 20 -> TypeError\n\n# after\nSearch(limit=cfg['limit'])             # int handled by Search\n# or\nLimit.from_dict({'limit': cfg['limit']})","handlingStrategy":"type-guard","validationCode":"def as_limit_dict(data):\n    '''Coerce common shapes into a Limit.from_dict-compatible dict.'''\n    if isinstance(data, bool):\n        raise TypeError('bool is not a valid limit payload')\n    if isinstance(data, int):\n        return {'limit': data}\n    if not isinstance(data, dict):\n        raise TypeError(f'limit payload must be a dict or int, got {type(data).__name__}')\n    return data\n\nSearch(limit=as_limit_dict(cfg['limit']))","typeGuard":"def is_limit_payload(data) -> bool:\n    return isinstance(data, dict) and set(data) <= {'offset', 'limit'}","tryCatchPattern":"try:\n    limit = Limit.from_dict(raw)\nexcept TypeError as e:\n    raise ValueError(f'invalid limit payload: {e}') from e","preventionTips":["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."],"tags":["validation","typeerror","pagination","limit","deserialization","chromadb"],"backgroundTag":"type-validation-failed","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}