{"record":{"id":"4583264bc35a8756","repo":"BerriAI/litellm","slug":"expected-document-dict-got-type-document-458326","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/mistral/ocr/transformation.py","lineNumber":183,"sourceCode":"            \"include_image_base64\": false,  # optional\n            ...\n        }\n\n        Args:\n            model: Model name (e.g., \"mistral-ocr-latest\")\n            document: Document dict from user (Mistral format) - already validated in main.py\n            optional_params: Already mapped optional parameters\n            headers: Request headers\n\n        Returns:\n            OCRRequestData with JSON data\n        \"\"\"\n        verbose_logger.debug(\"Mistral OCR transform_ocr_request - model: %s\", model)\n\n        # Document parameter is the Mistral-format dict from the user\n        # Just pass it through as-is to the Mistral API\n        if not isinstance(document, dict):\n            raise ValueError(f\"Expected document dict, got {type(document)}\")\n\n        # Build request data - use document dict directly\n        data: Final = {\n            \"model\": model,\n            \"document\": document,  # Pass through the Mistral-format document dict\n        }\n\n        # Add all optional parameters from the already-mapped optional_params\n        data.update(optional_params)\n\n        # No multipart files - using JSON\n        return OCRRequestData(data=data, files=None)\n\n    def transform_ocr_response(\n        self,\n        model: str,\n        raw_response: httpx.Response,\n        logging_obj: Any,","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/mistral/ocr/transformation.py#L165-L201","documentation":"Raised by litellm's Mistral OCR transformer in transform_ocr_request when the `document` argument is not a Python dict. Mistral's native OCR API expects a document object (e.g. {\"type\": \"document_url\", \"document_url\": ...} or image_url variant), and litellm passes the user-supplied document through verbatim, so it must already be a dict in Mistral format.","triggerScenarios":"Calling litellm.ocr(model='mistral/mistral-ocr-latest', document=<string or object>) — e.g. passing a bare URL string, a Pydantic model, or a file path instead of the Mistral-format dict.","commonSituations":"Developers coming from other OCR APIs that accept a URL string directly, or passing an unserialized object; also passing document as bytes.","solutions":["Pass document as a Mistral-format dict: {\"type\": \"document_url\", \"document_url\": \"https://...\"} for PDFs or {\"type\": \"image_url\", \"image_url\": \"https://...\"} for images.","If you built a Pydantic/dataclass object, call .model_dump() / .dict() first.","Never pass a raw URL string or file path as document for mistral models."],"exampleFix":"# before\nlitellm.ocr(model=\"mistral/mistral-ocr-latest\", document=\"https://x.com/a.pdf\")\n\n# after\nlitellm.ocr(\n    model=\"mistral/mistral-ocr-latest\",\n    document={\"type\": \"document_url\", \"document_url\": \"https://x.com/a.pdf\"},\n)","handlingStrategy":"type-guard","validationCode":"def is_mistral_document(doc: object) -> bool:\n    return isinstance(doc, dict) and doc.get(\"type\") in {\"document_url\", \"image_url\"} and (\n        \"document_url\" in doc or \"image_url\" in doc\n    )","typeGuard":"from typing import Any, TypeGuard\n\ndef is_mistral_ocr_document(value: Any) -> TypeGuard[dict]:\n    return (\n        isinstance(value, dict)\n        and isinstance(value.get(\"type\"), str)\n        and any(k in value for k in (\"document_url\", \"image_url\"))\n    )","tryCatchPattern":"try:\n    litellm.ocr(model=\"mistral/mistral-ocr-latest\", document=doc)\nexcept ValueError as e:\n    if \"Expected document dict\" in str(e):\n        raise TypeError(\"document must be a Mistral-format dict\") from e\n    raise","preventionTips":["Construct the document dict at the edge of your API, not inline at call sites.","Serialize Pydantic models with .model_dump() before passing.","Never pass a bare URL string as document for mistral OCR."],"tags":["mistral","ocr","type-validation","request-format"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}