BerriAI/litellm · error · ValueError
No choices in DeepSeek OCR response
Error message
No choices in DeepSeek OCR response
What it means
ValueError raised when the DeepSeek OCR response parses as JSON but contains no 'choices' array. The transformer expects a chat-style body ({'choices': [{'message': {'content': ...}}]}); a 200 response with any other shape fails here. The raw response text is debug-logged just before the raise, so verbose logging captures the actual body.
Source
Thrown at litellm/llms/vertex_ai/ocr/deepseek_transformation.py:270
Args:
model: Model name
raw_response: Raw HTTP response from Vertex AI
logging_obj: Logging object
**kwargs: Additional arguments
Returns:
OCRResponse in standard format
"""
verbose_logger.debug("Vertex AI DeepSeek OCR transform_ocr_response called")
verbose_logger.debug("Raw response: %s", raw_response.text)
try:
response_json: Final = raw_response.json()
# Extract OCR content from provider response
choices: Final = response_json.get("choices", [])
if not choices:
raise ValueError("No choices in DeepSeek OCR response")
message: Final = choices[0].get("message", {})
content: Final = message.get("content", "")
if not content:
raise ValueError("No content in DeepSeek OCR response")
# Try to parse content as JSON (OCR result might be JSON string)
ocr_data = None
try:
# If content is a JSON string, parse it
if isinstance(content, str) and content.strip().startswith("{"):
ocr_data = json.loads(content)
elif isinstance(content, dict):
ocr_data = content
else:
# If content is markdown text, create a single page with the markdown
ocr_data = {View on GitHub (pinned to 77b7c6c40c)
Solutions
- Enable verbose/debug logging to capture the 'Raw response: %s' line and see the actual body
- Confirm the model name routes to the DeepSeek OCR endpoint on Vertex
- If a proxy sits in front, verify it passes the Vertex body through unchanged
- Update litellm to the latest version in case the provider schema changed and litellm adapted
Defensive patterns
Strategy: try-catch
Try / catch
import litellm
litellm.verbose = True # the transformer debug-logs the raw body before raising
try:
resp = litellm.ocr(model=model, document=doc)
except ValueError as e:
if 'No choices' in str(e):
log.error('deepseek ocr: body without choices; check verbose logs for the raw response')
resp = litellm.ocr(model=model, document=doc) # single retry if transient
else:
raise Prevention
- Run with verbose logging in non-prod to capture raw OCR bodies
- Pin known-good litellm and Vertex model versions
- Route OCR traffic directly to Vertex, not through re-envelope proxies
When it happens
Trigger: Vertex returns 200 with an error or status object instead of choices; a schema change in the DeepSeek OCR model output; a proxy rewrites or strips the choices field.
Common situations: Model or endpoint version drift on Vertex; misrouted model name hitting a different endpoint; gateways that re-envelope responses.
Related errors
- No content in DeepSeek OCR response
- embedding response does not contain 'predictions', got {_jso
- Missing vertex_project - Set VERTEXAI_PROJECT environment va
- Expected document dict, got {type(document)}
- Unsupported document type: {doc_type}. Expected 'image_url'
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/ee5d3f3e8c6dfe35.
Report an issue: GitHub.