{"record":{"id":"6919c4140b027dbe","repo":"chroma-core/chroma","slug":"limit-limit-must-be-positive-got-limit","errorCode":null,"errorMessage":"Limit limit must be positive, got {limit}","messagePattern":"Limit limit must be positive, got (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"chromadb/execution/expression/operator.py","lineNumber":584,"sourceCode":"        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:\n            raise ValueError(f\"Unexpected keys in Limit dict: {unexpected_keys}\")\n\n        return Limit(offset=offset, limit=limit)\n\n\n@dataclass\nclass Projection:\n    document: bool = False\n    embedding: bool = False\n    metadata: bool = False\n    rank: bool = False\n    uri: bool = False\n","sourceCodeStart":566,"sourceCodeEnd":602,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/chromadb/execution/expression/operator.py#L566-L602","documentation":"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.","triggerScenarios":"Limit.from_dict({'limit': 0}); {'limit': -5}; computed sizes flooring to zero, e.g. {'limit': max(0, remaining)} when nothing remains.","commonSituations":"Clamping code producing 0; defaulting a missing config to 0 instead of None; UI 'show 0 rows' options forwarded verbatim to the query layer.","solutions":["Send limit=None (or omit the key / use Limit()) when you mean no limit.","Clamp computed sizes to at least 1: max(1, remaining).","Short-circuit '0 results' requests at your API layer instead of building a Search."],"exampleFix":"# before\nSearch(limit={'limit': max(0, remaining)})   # remaining=0 -> ValueError\n\n# after\nlimit = None if remaining <= 0 else remaining\nSearch(limit=limit)","handlingStrategy":"validation","validationCode":"def page_limit(requested):\n    if requested is None or requested <= 0:\n        return None          # no limit\n    return requested\n\nSearch(limit=page_limit(cfg.get('limit')))","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat 0/negative as 'unlimited' (None) or as a client error before building the payload.","Validate page_size >= 1 in request validation.","Document in your own API wrapper that limit=None means unlimited."],"tags":["validation","valueerror","pagination","limit","chromadb"],"backgroundTag":"out-of-range-value","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}