BerriAI/litellm · error · ValueError
Unsupported document type: {doc_type}. Expected 'image_url'
Error message
Unsupported document type: {doc_type}. Expected 'image_url' or 'document_url' What it means
ValueError raised when the document dict's 'type' field is neither 'image_url' nor 'document_url'. The DeepSeek OCR transformer branches only on those two literals, so a missing 'type' key (doc_type is None) or any other spelling is rejected before a request is built.
Source
Thrown at litellm/llms/vertex_ai/ocr/deepseek_transformation.py:169
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:
# For document URLs, we use image_url type as well (Vertex AI supports both)
content_item = {"type": "image_url", "image_url": document_url}
# Build DeepSeek OCR request
data: Final = {
"model": "deepseek-ai/" + model,
"messages": [{"role": "user", "content": [content_item]}],
}
# Add optional parameters (stream, temperature, etc.)
deepseek_ocr_params: Final = {}
for key, value in optional_params.items():View on GitHub (pinned to 77b7c6c40c)
Solutions
- Use exactly 'image_url' or 'document_url' as the type value
- Pair it with the matching sibling key: 'image_url' for images, 'document_url' for PDFs/documents
- Validate the enum before the call (see defense)
Example fix
# before
litellm.ocr(model='vertex_ai/deepseek-ai/deepseek-ocr', document={'type': 'image', 'url': img_url})
# after
litellm.ocr(model='vertex_ai/deepseek-ai/deepseek-ocr', document={'type': 'image_url', 'image_url': img_url}) Defensive patterns
Strategy: validation
Validate before calling
ALLOWED = ('image_url', 'document_url')
def normalize_document(doc: dict) -> dict:
t = doc.get('type')
if t == 'image':
doc = {**doc, 'type': 'image_url'}
elif t == 'file':
doc = {**doc, 'type': 'document_url'}
assert doc.get('type') in ALLOWED, f'type must be one of {ALLOWED}, got {t!r}'
return doc Type guard
def has_supported_doc_type(doc: dict) -> bool:
return doc.get('type') in ('image_url', 'document_url') Prevention
- Map upstream document types to image_url/document_url at your API boundary
- Reject documents without a recognized type early
- Keep a fixture test asserting your request builder emits only the two allowed types
When it happens
Trigger: document={'type': 'image', ...} or {'type': 'file', ...}; the 'type' key omitted entirely so doc_type is None; values copied from another OCR vendor's schema.
Common situations: Schema drift between OCR providers (Mistral uses image_url/document_url while other APIs use 'image' or 'file'); unvalidated user-supplied document descriptors.
Related errors
- Expected document dict, got {type(document)}
- Expected document dict, got {type(document)}
- 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/74e3307a56f0b6fb.
Report an issue: GitHub.