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 ID

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Increase max_attempts and/or poll_interval so the budget covers the expected task duration
  2. Optimize/scale the Pydantic AI agent so tasks finish faster
  3. 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

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


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