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

  1. 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.
  2. Shorten run time: trim input, split work into multiple runs, or disable unnecessary tools.
  3. Use the streaming path (stream=True), which receives events as they happen rather than polling to a deadline.
  4. 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

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

Related errors


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