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 soView on GitHub (pinned to 6c2dcb801b)
Solutions
- Manually GET the operation-location URL (from debug logs) with the same auth headers and inspect whether it returns an operation status document.
- Re-submit the batch operation — expired/invalid operation URLs often resolve on a fresh submission.
- Ensure api_base and credentials are valid so Azure returns real operation status responses.
- 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
- Start polling batch operations soon after submission; don't let operation URLs age out.
- Treat this error as non-retryable-with-same-input: fetch fresh state instead of hammering the same URL.
- Note that the error deliberately omits the response body (SSRF mitigation) — debug by fetching the URL yourself with proper auth.
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
- Rejected polling URL: {ssrf_err}
- Azure Document Intelligence: rejected polling URL ({ssrf_err
- MAVVRIK_API_ENDPOINT host must be a Mavvrik domain (e.g. htt
- Mavvrik FOCUS destination: {label} must be a GCS endpoint (s
- {field_name} cannot be a dot path segment
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/b2e99acc44aed729.
Report an issue: GitHub.