BerriAI/litellm · error · AzureOpenAIError

Polling response missing 'status' field

Error message

Polling response missing 'status' field

What it means

During Azure batch operation polling, the JSON returned from the operation-location URL must contain a top-level 'status' field. If missing, LiteLLM raises this 502 without echoing the body — deliberately, because if the polling URL hit an internal JSON API (e.g. a cloud metadata service) reflecting the body would turn a blind SSRF into a full-read SSRF (VERIA-51).

Source

Thrown at litellm/llms/azure/azure.py:921

                raise AzureOpenAIError(
                    status_code=502,
                    message=f"Rejected polling URL: {ssrf_err}",
                )
            response = await async_handler.get(
                url=operation_location_url,
                headers=headers,
            )

            await response.aread()

            timeout_secs: Final[int] = AZURE_OPERATION_POLLING_TIMEOUT
            start_time: Final = time.time()
            if "status" not in response.json():
                # Don't reflect the raw response body — when the polling
                # URL points at an internal JSON API (cloud metadata
                # service etc.) reflecting it here turns Blind SSRF into
                # Full-Read SSRF. VERIA-51.
                raise AzureOpenAIError(
                    status_code=502,
                    message="Polling response missing 'status' field",
                )
            while response.json()["status"] not in ["succeeded", "failed"]:
                if time.time() - start_time > timeout_secs:
                    raise AzureOpenAIError(status_code=408, message="Operation polling timed out.")

                await asyncio.sleep(int(response.headers.get("retry-after") or 10))
                response = await async_handler.get(
                    url=operation_location_url,
                    headers=headers,
                )
                await response.aread()

            if response.json()["status"] == "failed":
                error_data: Final = response.json()
                # Preserve Azure error details (e.g. content_policy_violation,
                # inner_error, content_filter_results) as structured body so

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Manually GET the operation-location URL (from debug logs) with the same auth headers and inspect whether it returns an operation status document.
  2. Re-submit the batch operation — expired/invalid operation URLs often resolve on a fresh submission.
  3. Ensure api_base and credentials are valid so Azure returns real operation status responses.
  4. Keep total polling time short and start polling promptly after submission to avoid URL expiry.

Example fix

# before
job = litellm.create_batch(..., completion_window='24h')
# ... poll hours later via litellm.poll_batch(job.id) -> 502 missing status

# after
job = litellm.create_batch(..., completion_window='24h')
status = litellm.poll_batch(job.id)  # poll soon after creation; retry once on 'missing status' before re-submitting
Defensive patterns

Strategy: try-catch

Validate before calling

async def poll_status_safely(url: str, headers: dict) -> dict | None:
    async with httpx.AsyncClient() as h:
        r = await h.get(url, headers=headers)
        try:
            body = r.json()
        except Exception:
            return None
        return body if isinstance(body, dict) and 'status' in body else None  # pre-check before relying on litellm polling

Try / catch

from litellm.exceptions import APIError

try:
    status = litellm.poll_batch(job.id)
except APIError as e:
    if "missing 'status'" in str(e):
        # operation URL likely expired or misrouted: re-submit once, then surface
        job = litellm.create_batch(...)
        status = litellm.poll_batch(job.id)
    else:
        raise

Prevention

When it happens

Trigger: The operation-location URL responds with JSON lacking 'status': a misrouted endpoint, an auth wall returning an error JSON, or (attack scenario) an internal service responding to the polled URL. Commonly also appears when Azure changes polling payload shape or the URL expires and returns an error document.

Common situations: Long-running batch jobs where the operation URL expired before polling; gateways rewriting polling responses; legitimate Azure error JSON (e.g. {"error": ...}) instead of an operation status document.

Related errors


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