BerriAI/litellm · error · ValueError
Expected document dict, got {type(document)}
Error message
Expected document dict, got {type(document)} What it means
ValueError raised in the DeepSeek OCR request transformer when the `document` argument is not a Python dict. The Mistral-compatible OCR interface expects document as {'type': ..., 'image_url'|'document_url': ...}; the isinstance(document, dict) check fails for strings, lists, or None before any request is built.
Source
Thrown at litellm/llms/vertex_ai/ocr/deepseek_transformation.py:157
Converts OCR document format to the Vertex AI DeepSeek OCR payload:
- Input: {"type": "image_url", "image_url": "gs://..."}
- Output: {"model": "deepseek-ai/deepseek-ocr-maas", "messages": [{"role": "user", "content": [{"type": "image_url", "image_url": "gs://..."}]}]}
Args:
model: Model name (e.g., "deepseek-ai/deepseek-ocr-maas")
document: Document dict from user (Mistral OCR format)
optional_params: Already mapped optional parameters
headers: Request headers
**kwargs: Additional arguments
Returns:
OCRRequestData with JSON data for the DeepSeek OCR endpoint
"""
verbose_logger.debug("Vertex AI DeepSeek OCR transform_ocr_request (sync) called")
if not isinstance(document, dict):
raise ValueError(f"Expected document dict, got {type(document)}")
# Extract document type and URL
doc_type: Final = document.get("type")
image_url = None
document_url = None
if doc_type == "image_url":
image_url = document.get("image_url", "")
elif doc_type == "document_url":
document_url = document.get("document_url", "")
else:
raise ValueError(f"Unsupported document type: {doc_type}. Expected 'image_url' or 'document_url'")
# Build DeepSeek OCR message content
content_item = {}
if image_url:
content_item = {"type": "image_url", "image_url": image_url}
elif document_url:View on GitHub (pinned to 77b7c6c40c)
Solutions
- Pass document as a dict: {'type': 'document_url', 'document_url': 'https://...'}
- json.loads() the payload first if it arrives as a JSON string
- Add a type guard before the call (see defense)
Example fix
# before
resp = litellm.ocr(model='vertex_ai/deepseek-ai/deepseek-ocr', document='https://example.com/doc.pdf')
# after
resp = litellm.ocr(
model='vertex_ai/deepseek-ai/deepseek-ocr',
document={'type': 'document_url', 'document_url': 'https://example.com/doc.pdf'},
) Defensive patterns
Strategy: type-guard
Validate before calling
def is_ocr_document(doc: object) -> bool:
return (
isinstance(doc, dict)
and isinstance(doc.get('type'), str)
and doc['type'] in ('image_url', 'document_url')
)
assert is_ocr_document(document), f'document must be a dict, got {type(document)}' Type guard
from typing import Any
def is_ocr_document(value: Any) -> bool:
'''Narrow the OCR `document` argument to the accepted dict shape.'''
if not isinstance(value, dict):
return False
if value.get('type') not in ('image_url', 'document_url'):
return False
url_key = value['type']
return isinstance(value.get(url_key), str) and bool(value[url_key]) Try / catch
try:
resp = litellm.ocr(model=model, document=document)
except ValueError as e:
if str(e).startswith('Expected document dict'):
document = {'type': 'document_url', 'document_url': str(document)}
resp = litellm.ocr(model=model, document=document)
else:
raise Prevention
- Always construct the document dict at your application boundary
- Parse JSON payloads before passing them to the OCR API
- Reject non-dict documents in your own input validation layer
When it happens
Trigger: Calling OCR with document='https://host/doc.pdf' (bare string), document=[{...}] (list), or an unparsed JSON string; passing None because the caller's payload construction failed silently.
Common situations: Porting code from an API that takes a plain URL string; forwarding unvalidated user input; forgetting json.loads on a JSON-encoded body.
Related errors
- Expected document dict, got {type(document)}
- Unsupported document type: {doc_type}. Expected 'image_url'
- Missing vertex_project - Set VERTEXAI_PROJECT environment va
- No choices in DeepSeek OCR response
- No content in DeepSeek OCR response
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/ef876c38f474dde8.
Report an issue: GitHub.