{"record":{"id":"f775c05d1bf379e4","repo":"chroma-core/chroma","slug":"limit-offset-must-be-an-integer-got-type-offset","errorCode":null,"errorMessage":"Limit offset must be an integer, got {type(offset).__name__}","messagePattern":"Limit offset must be an integer, got (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"chromadb/execution/expression/operator.py","lineNumber":571,"sourceCode":"        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\n        # Check for unexpected keys\n        allowed_keys = {\"offset\", \"limit\"}\n        unexpected_keys = set(data.keys()) - allowed_keys\n        if unexpected_keys:","sourceCodeStart":553,"sourceCodeEnd":589,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/chromadb/execution/expression/operator.py#L553-L589","documentation":"Inside Limit.from_dict, the 'offset' field must be a Python int; floats and numeric strings fail isinstance(offset, int) and raise TypeError even when they look numeric (10.5, '10'). The check runs on data.get('offset', 0), so a bad value anywhere in the dict is caught before Limit is built.","triggerScenarios":"Limit.from_dict({'offset': 10.5}); Search(limit={'offset': '10'}); pagination math that mixes in a float, e.g. {'offset': int(size * (page - 1.0))} before the cast.","commonSituations":"Computed offsets using float arithmetic; YAML values parsed as strings ('10'); strict JSON decoders that return 10.0 for every number; form fields arriving as strings.","solutions":["Send a plain int: {'offset': 10}.","Coerce known-clean values before parsing: {'offset': int(offset)} (for floats, only when value.is_integer()).","Declare offset as an integer field in your config/pydantic schema so it arrives typed."],"exampleFix":"# before\nSearch(limit={'offset': '10', 'limit': 20})   # -> TypeError: got str\n\n# after\nSearch(limit={'offset': 10, 'limit': 20})\n# or, for untrusted input\nSearch(limit={'offset': int(offset_value), 'limit': 20})","handlingStrategy":"validation","validationCode":"def normalize_offset(data: dict) -> dict:\n    off = data.get('offset', 0)\n    if isinstance(off, bool):\n        raise TypeError('offset must be an int, not bool')\n    if isinstance(off, float) and off.is_integer():\n        return {**data, 'offset': int(off)}\n    if isinstance(off, str) and off.lstrip('-').isdigit():\n        return {**data, 'offset': int(off)}\n    return data\n\nSearch(limit=normalize_offset(limit_cfg))","typeGuard":"def has_valid_offset(data) -> bool:\n    off = data.get('offset', 0) if isinstance(data, dict) else None\n    return isinstance(off, int) and not isinstance(off, bool)","tryCatchPattern":null,"preventionTips":["Keep pagination arithmetic in ints (use // instead of /).","Declare offset as an integer field in config schemas so it arrives typed.","Unit-test offset boundaries (0, 1, large) in one shared helper."],"tags":["validation","typeerror","pagination","offset","chromadb"],"backgroundTag":"type-validation-failed","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}