{"record":{"id":"edbd1f86e37317d8","repo":"BerriAI/litellm","slug":"pages-integers-must-be-0-mistral-0-based-ind","errorCode":null,"errorMessage":"`pages` integers must be >= 0 (Mistral 0-based indices)","messagePattern":"`pages` integers must be >= 0 \\(Mistral 0-based indices\\)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/llms/azure_ai/ocr/document_intelligence/transformation.py","lineNumber":158,"sourceCode":"        \"\"\"\n        pages_pattern: Final = re.compile(r\"^\\s*\\d+(-\\d+)?(\\s*,\\s*\\d+(-\\d+)?)*\\s*$\")\n\n        if isinstance(pages, str):\n            if not pages_pattern.match(pages):\n                raise ValueError(\n                    f\"Invalid `pages` string for Azure Document Intelligence: \"\n                    f\"{pages!r}. Expected format like '1-3,5,7-9'.\"\n                )\n            return pages.replace(\" \", \"\")\n\n        if isinstance(pages, list):\n            if len(pages) == 0:\n                return \"\"\n            if any(isinstance(p, bool) for p in pages):\n                raise ValueError(\"`pages` must be integers, not booleans\")\n            if all(isinstance(p, int) for p in pages):\n                if any(p < 0 for p in pages):\n                    raise ValueError(\"`pages` integers must be >= 0 (Mistral 0-based indices)\")\n                # Mistral 0-based -> Azure 1-based.\n                return \",\".join(str(p + 1) for p in sorted(set(pages)))\n            if all(isinstance(p, str) for p in pages):\n                joined: Final = \",\".join(p.strip() for p in pages)\n                if not pages_pattern.match(joined):\n                    raise ValueError(\n                        f\"Invalid `pages` list for Azure Document Intelligence: \"\n                        f\"{pages!r}. Expected tokens like '1' or '3-5'.\"\n                    )\n                return joined\n\n        raise ValueError(\"`pages` must be a list[int] (0-based, Mistral-style) or a string like '1-3,5,7-9'.\")\n\n    @staticmethod\n    def _normalize_features_param(features: object) -> str:\n        \"\"\"\n        Convert a caller-provided `features` value to Azure DI's query-string\n        form (comma-joined feature names, e.g. \"keyValuePairs,languages\").","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/azure_ai/ocr/document_intelligence/transformation.py#L140-L176","documentation":"Raised when `pages` is a list of integers but at least one is negative. LiteLLM treats list[int] input as Mistral-style 0-based page indices and converts them to Azure's 1-based format, so negative values have no valid meaning and are rejected before the request. The check runs during request transformation, ahead of any Azure call.","triggerScenarios":"Calling azure_ai doc-intelligence OCR with optional_params={\"pages\": [0, -1]} or pages=[-1] — any list[int] containing a value < 0.","commonSituations":"Off-by-one bugs where code computes page indices with a -1 adjustment and undershoots; parsing user input like '-1' into ints; mixing up 0-based and 1-based conventions and trying to compensate.","solutions":["Use non-negative 0-based indices: [0, 1, 2] means pages 1-3 in Azure terms.","If you meant 1-based Azure pages, pass a string like '1-3' instead of a list.","Clamp or validate computed indices (e.g. max(p, 0)) before the call."],"exampleFix":"# before\npages = [current_page - 1 for current_page in selected]  # selected[0]==0 -> -1\nlitellm.aocr_document(model=..., document=doc, pages=pages)\n\n# after\npages = [max(p, 0) for p in (current_page - 1 for current_page in selected)]\nlitellm.aocr_document(model=..., document=doc, pages=pages)","handlingStrategy":"validation","validationCode":"def valid_page_indices(pages: list[int]) -> bool:\n    return all(p >= 0 for p in pages if isinstance(p, int) and not isinstance(p, bool))","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Clamp computed indices with max(p, 0).","Remember list[int] is 0-based Mistral-style; use a string for 1-based Azure pages."],"tags":["azure","document-intelligence","ocr","validation","pages","off-by-one"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}