BerriAI/litellm · error · AzureAIAgentsError
Run timed out waiting for completion
Error message
Run timed out waiting for completion
What it means
In the sync (non-streaming) Azure AI Agents path, LiteLLM polls the run status up to MAX_POLL_ATTEMPTS times, sleeping POLL_INTERVAL_SECONDS between polls. If the run never reaches 'completed' within that budget, the for-loop's else clause raises AzureAIAgentsError with status_code 408 and message 'Run timed out waiting for completion'. The run may still be executing on Azure — this is a client-side give-up, not proof of failure.
Source
Thrown at litellm/llms/azure_ai/agents/handler.py:348
# Step 4: Poll for completion
status_url: Final = self._build_run_status_url(api_base, thread_id, run_id, api_version)
for _ in range(self.config.MAX_POLL_ATTEMPTS):
response = make_request("GET", status_url)
self._check_response(response, [200], "Failed to get run status")
status = response.json().get("status")
verbose_logger.debug("Run status: %s", status)
if status == "completed":
break
elif status in ["failed", "cancelled", "expired"]:
error_msg = response.json().get("last_error", {}).get("message", "Unknown error")
raise AzureAIAgentsError(status_code=500, message=f"Run {status}: {error_msg}")
time.sleep(self.config.POLL_INTERVAL_SECONDS)
else:
raise AzureAIAgentsError(status_code=408, message="Run timed out waiting for completion")
# Step 5: Get messages
response = make_request("GET", self._build_list_messages_url(api_base, thread_id, api_version))
self._check_response(response, [200], "Failed to get messages")
content, annotations = self._extract_content_from_messages(response.json())
return thread_id, content, annotations
# -------------------------------------------------------------------------
# Async Completion
# -------------------------------------------------------------------------
async def acompletion(
self,
model: str,
messages: list[dict[str, Any]],
api_base: str,
api_key: str,
model_response: ModelResponse,View on GitHub (pinned to 6c2dcb801b)
Solutions
- Catch the 408 and poll the thread's run yourself via the Azure SDK/REST (you still have thread_id and run_id) instead of assuming failure.
- Shorten run time: trim input, split work into multiple runs, or disable unnecessary tools.
- Use the streaming path (stream=True), which receives events as they happen rather than polling to a deadline.
- Check Azure Foundry metrics/portal for run latency spikes if timeouts are new.
Defensive patterns
Strategy: fallback
Try / catch
try:
result = litellm.completion(model='azure_ai_agents/agent', messages=m)
except Exception as e:
if type(e).__name__ == 'AzureAIAgentsError' and getattr(e, 'status_code', None) == 408:
result = poll_run_via_azure_sdk(thread_id, run_id) # run may still complete
else:
raise Prevention
- Prefer stream=True for any agent expected to run longer than a few seconds.
- Alert on 408 rate — sustained timeouts mean agent/tool slowness, not client bugs.
- Keep thread_id/run_id around so a 408 is recoverable, not a dead end.
When it happens
Trigger: Long-running agent runs (big documents, multi-step tool chains, code interpreter) whose total time exceeds MAX_POLL_ATTEMPTS * POLL_INTERVAL_SECONDS; Azure under heavy load with slow run scheduling; a stuck run that stays 'queued'/'in_progress' indefinitely.
Common situations: Switching a prototype agent to a production workload with much longer prompts; region capacity issues making runs slow to start; polling defaults tuned for short chat runs and never adjusted.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Run {status}: {error_msg}
- Azure Document Intelligence operation polling timed out afte
- Task {task_id} did not complete within {max_attempts * poll_
- Polling response missing 'status' field
- {error_msg}: {response.text}
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/760dc51a37ab4b9d.
Report an issue: GitHub.