BerriAI/litellm · error · ValueError

Azure Document Intelligence analysis failed with status: {op

Error message

Azure Document Intelligence analysis failed with status: {operation.status}

What it means

Raised after polling completes when the final operation document's status is not 'succeeded'. The response is parsed into AzureDocumentIntelligenceOperation; a terminal status like 'failed' (or anything else) at transform time produces this ValueError naming the actual status. It complements the per-poll status check and fires in the response-transformation path (_transform_completed_response).

Source

Thrown at litellm/llms/azure_ai/ocr/document_intelligence/transformation.py:609

        except SSRFError as ssrf_err:
            raise ValueError(f"Azure Document Intelligence: rejected polling URL ({ssrf_err})")

        poll_headers = {"Ocp-Apim-Subscription-Key": raw_response.request.headers.get("Ocp-Apim-Subscription-Key", "")}
        return operation_url, poll_headers

    def _transform_completed_response(self, model: str, raw_response: httpx.Response) -> OCRResponse:
        """
        Transform a completed Azure Document Intelligence analyze operation
        into the Mistral OCR response shape, preserving Azure-native
        `analyzeResult` fields (`content`, `tables`, `keyValuePairs`) as
        top-level response fields.
        """
        operation: Final = AzureDocumentIntelligenceOperation.model_validate(raw_response.json())

        verbose_logger.debug("Azure Document Intelligence response status: %s", operation.status)

        if operation.status != "succeeded":
            raise ValueError(f"Azure Document Intelligence analysis failed with status: {operation.status}")

        analyze_result: Final = (
            operation.analyzeResult if operation.analyzeResult is not None else AzureDocumentIntelligenceAnalyzeResult()
        )
        mistral_pages: Final = [self._transform_azure_page(azure_page) for azure_page in analyze_result.pages]
        usage_info: Final = OCRUsageInfo(pages_processed=len(mistral_pages), doc_size_bytes=None)

        return OCRResponse(
            pages=mistral_pages,
            model=model,
            usage_info=usage_info,
            object="ocr",
            content=analyze_result.content,
            tables=analyze_result.tables,
            keyValuePairs=analyze_result.keyValuePairs,
        )

    def transform_ocr_response(

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Inspect the status in the error message; if 'failed', re-submit and capture Azure's analyzeResult/error details, then fix the document (format, protection, size).
  2. Pre-screen documents client-side (valid PDF, not encrypted, within page/size limits).
  3. Upgrade LiteLLM if a new terminal status is being reported unhandled.
Defensive patterns

Strategy: try-catch

Try / catch

try:
    resp = litellm.aocr_document(model=m, document=doc)
except ValueError as e:
    if "analysis failed with status" in str(e):
        record_failure(doc, status=str(e))
        return None
    raise

Prevention

When it happens

Trigger: The last poll (or the sync response) carrying status 'failed' — corrupted document, unsupported content, size limits — or an unexpected terminal status reaching the transformer; operation.status != 'succeeded' after the loop exits.

Common situations: Same root causes as analysis failure: protected/corrupt PDFs, oversized documents, low-quality scans, Azure service errors; also race conditions where a non-terminal poll slips through and lands here.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/d84263c0177f1134. Report an issue: GitHub.