{"record":{"id":"7731bff6015e7d12","repo":"BerriAI/litellm","slug":"invalid-pages-string-for-azure-document-intellig","errorCode":null,"errorMessage":"Invalid `pages` string for Azure Document Intelligence: {pages!r}. Expected format like '1-3,5,7-9'.","messagePattern":"Invalid `pages` string for Azure Document Intelligence: (.+?)\\. Expected format like '1-3,5,7-9'\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/llms/azure_ai/ocr/document_intelligence/transformation.py","lineNumber":145,"sourceCode":"\n    @staticmethod\n    def _normalize_pages_param(pages: Any) -> str:\n        \"\"\"\n        Convert a caller-provided `pages` value to Azure DI's query-string\n        form. Azure expects 1-based page numbers, grammar: `^(\\\\d+(-\\\\d+)?)(,\\\\s*(\\\\d+(-\\\\d+)?))*$`.\n\n        Accepted inputs:\n          - list[int]: Mistral-style 0-based indices. Converted to 1-based\n            and joined (e.g. [0,1,2] -> \"1,2,3\").\n          - 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):","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/azure_ai/ocr/document_intelligence/transformation.py#L127-L163","documentation":"Thrown while normalizing the `pages` parameter for Azure Document Intelligence OCR when the caller passes a string that does not match the expected Azure page-range syntax (digits and hyphenated ranges, comma-separated, e.g. '1-3,5,7-9'). The string is validated against a regex before being forwarded to Azure, because Azure DI only accepts that exact query-string format. Any deviation (letters, double commas, 'page 1', semicolons) is rejected before the request is sent.","triggerScenarios":"Calling litellm.oclr/aocr with model 'azure_ai/doc-intelligence/...' and optional_params={\"pages\": \"1;3;5\"} or \"1..3\" or \"pages 1-3\" or \"1,,2\" — anything failing ^\\s*\\d+(-\\d+)?(\\s*,\\s*\\d+(-\\d+)?)*\\s*$. Note ranges here are Azure-native 1-based.","commonSituations":"Porting code from another OCR API whose pages syntax differs; user input passed through unvalidated; copy-pasting '1 - 3' style with stray characters; assuming 0-based or interval syntax like '1:3'.","solutions":["Format the string as comma-separated 1-based pages or ranges: '1-3,5,7-9' (spaces around commas are stripped, other whitespace only at the ends).","If you have 0-based Mistral-style indices, pass a list[int] instead — LiteLLM converts to 1-based for you.","Sanitize user-provided page input before passing it as `pages`."],"exampleFix":"# before\nresult = litellm.aocr_document(model=\"azure_ai/doc-intelligence/prebuilt-read\", document=doc, pages=\"pages 1 to 3\")\n\n# after\nresult = litellm.aocr_document(model=\"azure_ai/doc-intelligence/prebuilt-read\", document=doc, pages=\"1-3\")","handlingStrategy":"validation","validationCode":"import re\nPAGES_RE = re.compile(r\"^\\s*\\d+(-\\d+)?(\\s*,\\s*\\d+(-\\d+)?)*\\s*$\")\ndef valid_pages_str(pages: str) -> bool:\n    return bool(PAGES_RE.match(pages))","typeGuard":"def is_azure_pages_string(v: object) -> bool:\n    import re\n    return isinstance(v, str) and bool(re.match(r\"^\\s*\\d+(-\\d+)?(\\s*,\\s*\\d+(-\\d+)?)*\\s*$\", v))","tryCatchPattern":null,"preventionTips":["Always emit pages strings from structured data (ints/ranges) rather than free-form user text.","Prefer list[int] input; let LiteLLM format the string.","Validate user-supplied page selections against the regex before calling."],"tags":["azure","document-intelligence","ocr","validation","pages"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}