BerriAI/litellm · error · TimeoutError
Task {task_id} did not complete within {max_attempts * poll_
Error message
Task {task_id} did not complete within {max_attempts * poll_interval} seconds What it means
TimeoutError raised when the polling loop for a Pydantic AI task exhausts max_attempts * poll_interval seconds without the task reaching 'completed' (and without hitting failed/canceled). The task may still be running server-side.
Source
Thrown at litellm/a2a_protocol/providers/pydantic_ai_agents/transformation.py:151
},
)
response.raise_for_status()
poll_data = _STR_KEY_DICT_ADAPTER.validate_python(response.json())
result = _STR_KEY_DICT_ADAPTER.validate_python(poll_data.get("result", {}))
status = _STR_KEY_DICT_ADAPTER.validate_python(result.get("status", {}))
state = status.get("state", "")
verbose_logger.debug("Pydantic AI: Poll attempt %s/%s, state=%s", attempt + 1, max_attempts, state)
if state == "completed":
return poll_data
elif state in ("failed", "canceled"):
raise Exception(f"Task {task_id} ended with state: {state}")
await asyncio.sleep(poll_interval)
raise TimeoutError(f"Task {task_id} did not complete within {max_attempts * poll_interval} seconds")
@staticmethod
async def _send_and_poll_raw(
api_base: str,
request_id: str,
params: "_SupportsModelDump | _SupportsPydanticDict | Mapping[str, object]",
timeout: float = 60.0,
agent_extra_headers: dict[str, str] | None = None,
) -> dict[str, object]:
"""
Send a request to Pydantic AI agent and return the raw task response.
This is an internal method used by both non-streaming and streaming handlers.
Returns the raw Pydantic AI task format with history/artifacts.
Args:
api_base: Base URL of the Pydantic AI agent
request_id: A2A JSON-RPC request IDView on GitHub (pinned to 6c2dcb801b)
Solutions
- Increase max_attempts and/or poll_interval so the budget covers the expected task duration
- Optimize/scale the Pydantic AI agent so tasks finish faster
- On TimeoutError, optionally re-query the task by id to check if it completed late
Defensive patterns
Strategy: retry
Validate before calling
expected_max_seconds = 120 max_attempts, poll_interval = 60, 2 # budget 120s > expected # ensure max_attempts * poll_interval >= worst-case task duration
Try / catch
import asyncio
try:
result = await poll_task(task_id)
except TimeoutError:
logger.warning("task %s poll timed out; retrying once", task_id)
await asyncio.sleep(5)
result = await poll_task(task_id) # task may have completed late Prevention
- Size max_attempts * poll_interval above the agent's worst-case task duration
- Track p95 task duration and alert when polls approach the budget
- Treat late completion as a possible eventual success: re-check by task id on timeout
When it happens
Trigger: Long-running agent task that never transitions to completed within the poll budget, e.g. max_attempts=60, poll_interval=1 and the task takes 90s.
Common situations: Slow LLM/tool calls inside the agent; poll budget not scaled with expected workload; network stalls between LiteLLM and the agent.
Related errors
- Task {task_id} ended with state: {state}
- api_base is required for PydanticAIProviderConfig
- api_base is required for Pydantic AI agents
- api_base is required for Pydantic AI agents
- request is required
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/7551961d6829a287.
Report an issue: GitHub.