{"record":{"id":"0d8ee9d2a90e33e7","repo":"BerriAI/litellm","slug":"expected-document-dict-got-type-document-0d8ee9","errorCode":null,"errorMessage":"Expected document dict, got {type(document)}","messagePattern":"Expected document dict, got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/llms/azure_ai/ocr/transformation.py","lineNumber":182,"sourceCode":"        Transform OCR request for Azure AI, converting URLs to base64 data URIs (sync).\n\n        Azure AI OCR doesn't have internet access, so we automatically fetch\n        any URLs and convert them to base64 data URIs synchronously.\n\n        Args:\n            model: Model name\n            document: Document dict from user\n            optional_params: Already mapped optional parameters\n            headers: Request headers\n            **kwargs: Additional arguments\n\n        Returns:\n            OCRRequestData with JSON data\n        \"\"\"\n        verbose_logger.debug(\"Azure AI OCR transform_ocr_request (sync) - model: %s\", model)\n\n        if not isinstance(document, dict):\n            raise ValueError(f\"Expected document dict, got {type(document)}\")\n\n        # Check if we need to convert URL to base64\n        doc_type: Final = document.get(\"type\")\n        transformed_document: Final = document.copy()\n\n        if doc_type == \"document_url\":\n            document_url: Final = document.get(\"document_url\", \"\")\n            # If it's not already a data URI, convert it\n            if document_url and not document_url.startswith(\"data:\"):\n                verbose_logger.debug(\"Azure AI OCR: Converting document URL to base64 data URI (sync)\")\n                data_uri = self._convert_url_to_data_uri_sync(url=document_url)\n                transformed_document[\"document_url\"] = data_uri\n        elif doc_type == \"image_url\":\n            image_url: Final = document.get(\"image_url\", \"\")\n            # If it's not already a data URI, convert it\n            if image_url and not image_url.startswith(\"data:\"):\n                verbose_logger.debug(\"Azure AI OCR: Converting image URL to base64 data URI (sync)\")\n                data_uri = self._convert_url_to_data_uri_sync(url=image_url)","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/azure_ai/ocr/transformation.py#L164-L200","documentation":"The sync OCR request transformer requires the document argument to be a Python dict (LiteLLM's document format, e.g. {'type': 'document_url', 'document_url': ...}). If you pass anything else — a string URL, a JSON string, a pydantic object — this ValueError fires before any network call.","triggerScenarios":"Calling litellm.ocr(model=..., document='https://example.com/doc.pdf') instead of wrapping the URL in a dict; passing a JSON-encoded string like json.dumps({...}); passing an object with attributes instead of a plain dict.","commonSituations":"Porting code from the raw Mistral OCR API that takes a URL string; forgetting the required 'type' envelope after reading docs quickly; data flowing from another service as a string payload.","solutions":["Wrap the URL: document={'type': 'document_url', 'document_url': 'https://example.com/doc.pdf'}","If you have a JSON string, parse it first: document=json.loads(payload)","For base64 input use {'type': 'document_url', 'document_url': 'data:application/pdf;base64,...'} or the image variant {'type': 'image_url', 'image_url': ...}"],"exampleFix":"# before\nresult = litellm.ocr(model='azure_ai/mistral-ocr', document='https://example.com/invoice.pdf')\n\n# after\nresult = litellm.ocr(model='azure_ai/mistral-ocr', document={'type': 'document_url', 'document_url': 'https://example.com/invoice.pdf'})","handlingStrategy":"type-guard","validationCode":"def to_ocr_document(value) -> dict:\n    if not isinstance(value, dict):\n        raise TypeError('document must be a dict like {\"type\": \"document_url\", \"document_url\": ...}')\n    return value","typeGuard":"def is_ocr_document(value) -> bool:\n    return isinstance(value, dict) and isinstance(value.get('type'), str)","tryCatchPattern":"try:\n    litellm.ocr(model='azure_ai/mistral-ocr', document=doc)\nexcept ValueError as e:\n    if 'Expected document dict' in str(e):\n        doc = {'type': 'document_url', 'document_url': str(doc)}\n    else:\n        raise","preventionTips":["Always build the document dict through one helper function instead of inline literals","Parse JSON strings at the system boundary, never inside the LLM call"],"tags":["azure","ocr","type-error","validation"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}