{"record":{"id":"84f1dc7f904556e2","repo":"BerriAI/litellm","slug":"no-content-in-deepseek-ocr-response","errorCode":null,"errorMessage":"No content in DeepSeek OCR response","messagePattern":"No content in DeepSeek OCR response","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/llms/vertex_ai/ocr/deepseek_transformation.py","lineNumber":276,"sourceCode":"        Returns:\n            OCRResponse in standard format\n        \"\"\"\n        verbose_logger.debug(\"Vertex AI DeepSeek OCR transform_ocr_response called\")\n        verbose_logger.debug(\"Raw response: %s\", raw_response.text)\n\n        try:\n            response_json: Final = raw_response.json()\n\n            # Extract OCR content from provider response\n            choices: Final = response_json.get(\"choices\", [])\n            if not choices:\n                raise ValueError(\"No choices in DeepSeek OCR response\")\n\n            message: Final = choices[0].get(\"message\", {})\n            content: Final = message.get(\"content\", \"\")\n\n            if not content:\n                raise ValueError(\"No content in DeepSeek OCR response\")\n\n            # Try to parse content as JSON (OCR result might be JSON string)\n            ocr_data = None\n            try:\n                # If content is a JSON string, parse it\n                if isinstance(content, str) and content.strip().startswith(\"{\"):\n                    ocr_data = json.loads(content)\n                elif isinstance(content, dict):\n                    ocr_data = content\n                else:\n                    # If content is markdown text, create a single page with the markdown\n                    ocr_data = {\n                        \"pages\": [{\"index\": 0, \"markdown\": content}],\n                        \"model\": model,\n                        \"usage_info\": response_json.get(\"usage\", {}),\n                    }\n            except json.JSONDecodeError:\n                # If JSON parsing fails, treat content as markdown","sourceCodeStart":258,"sourceCodeEnd":294,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/llms/vertex_ai/ocr/deepseek_transformation.py#L258-L294","documentation":"ValueError raised when the DeepSeek OCR response has choices but choices[0].message.content is empty (missing key, empty string, or empty dict). Without content the transformer cannot build OCR pages, so it fails immediately after the 'no choices' check.","triggerScenarios":"The model returns an empty message (safety filter, internal truncation, transient model failure); the message contains only other fields; upstream returns content: ''.","commonSituations":"Documents that trip safety filtering; oversized or corrupt inputs producing empty output; transient service hiccups.","solutions":["Enable verbose logging and inspect the raw response text to see what the model actually returned","Retry once - empty content is often transient","If systematic, the document may be unsupported or too large: try another format, fewer pages, or re-encode the file"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"for attempt in range(2):\n    try:\n        resp = litellm.ocr(model=model, document=doc)\n        break\n    except ValueError as e:\n        if 'No content' in str(e) and attempt == 0:\n            continue  # empty content is frequently transient\n        raise","preventionTips":["Pre-check that documents are readable and non-empty before OCR","Cap document size to the model's limits","Retry empty-content responses once before surfacing errors to users"],"tags":["vertex-ai","ocr","empty-response","content-missing"],"backgroundTag":"empty-response-body","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}