{"record":{"id":"8c22f880aabe1cf0","repo":"BerriAI/litellm","slug":"pages-must-be-integers-not-booleans","errorCode":null,"errorMessage":"`pages` must be integers, not booleans","messagePattern":"`pages` must be integers, not booleans","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/llms/azure_ai/ocr/document_intelligence/transformation.py","lineNumber":155,"sourceCode":"          - list[str]: tokens like \"1\" or \"3-5\". Validated, joined as-is\n            (treated as Azure-native, i.e. 1-based).\n          - str: already in Azure format. Validated and whitespace-stripped.\n        \"\"\"\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:","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/azure_ai/ocr/document_intelligence/transformation.py#L137-L173","documentation":"Raised when the `pages` parameter passed to Azure Document Intelligence OCR is a list containing a boolean. Python bools are subclasses of int, so [True, 2] would otherwise silently become '2,3' (True→1-based 2); LiteLLM explicitly rejects booleans to prevent that silent corruption. It fires before any network call, during request transformation.","triggerScenarios":"Calling the azure_ai doc-intelligence OCR endpoint with optional_params={\"pages\": [True, False]} or [1, True] — any list where isinstance(p, bool) is True for at least one element.","commonSituations":"Building the pages list from flags/checkboxes or JSON where true/false leaked into an integer list; data deserialization (e.g. pydantic with loose typing, JSON 'true') inserting booleans.","solutions":["Pass only real integers in the list: [0, 1, 2] (0-based Mistral-style, converted to 1-based automatically).","Filter/convert booleans before the call if they come from untyped input.","Alternatively pass a validated string like '1-3,5'."],"exampleFix":"# before\npages = [0, 1, True]  # bool leaked in from a config flag\nlitellm.aocr_document(model=\"azure_ai/doc-intelligence/prebuilt-layout\", document=doc, pages=pages)\n\n# after\npages = [p for p in pages if isinstance(p, int) and not isinstance(p, bool)]\nlitellm.aocr_document(model=\"azure_ai/doc-intelligence/prebuilt-layout\", document=doc, pages=pages)","handlingStrategy":"type-guard","validationCode":"def clean_pages(pages: list) -> list[int]:\n    return [p for p in pages if isinstance(p, int) and not isinstance(p, bool)]","typeGuard":"def is_int_pages_list(v: object) -> bool:\n    return isinstance(v, list) and all(isinstance(p, int) and not isinstance(p, bool) for p in v)","tryCatchPattern":null,"preventionTips":["Type page lists as list[int] in pydantic/TypedDict models so bools can't enter.","Sanitize untyped JSON input (filter bools) before passing `pages`."],"tags":["azure","document-intelligence","ocr","type-validation","pages"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}