BerriAI/litellm · error · RuntimeError
Cannot retry A2A localhost URL fix: the client was not…
Error message
Cannot retry A2A localhost URL fix: the client was not created by create_a2a_client, so no LiteLLM httpx client is attached.
What it means
During a localhost-URL retry, LiteLLM reuses the shared httpx client it attached to the a2a client at creation time (the _litellm_httpx_client attribute), because it carries this agent's trace-id and auth headers. An externally constructed a2a-sdk client lacks that attribute, so the retry aborts with this RuntimeError rather than silently losing header context. Only clients built by litellm.a2a_protocol.create_a2a_client are retryable.
Solutions
- Build the client with litellm.a2a_protocol.create_a2a_client(base_url=..., extra_headers=...) instead of the raw a2a-sdk builder
- Or skip client management entirely: pass api_base (plus agent_extra_headers if needed) to asend_message/asend_message_streaming
- If you need custom httpx behavior, check create_a2a_client's supported options (timeout, extra_headers) before building your own
Example fix
# before
from a2a.client import ClientBuilder
client = ClientBuilder(httpx_client=my_httpx).build()
await asend_message(a2a_client=client, request=req)
# after
from litellm.a2a_protocol import create_a2a_client
client = await create_a2a_client(base_url='http://agent:10001', extra_headers={'Authorization': '...'})
await asend_message(a2a_client=client, request=req, api_base='http://agent:10001') Defensive patterns
Strategy: type-guard
Validate before calling
httpx_client = getattr(a2a_client, '_litellm_httpx_client', None)
if httpx_client is None:
# not created by create_a2a_client: rebuild it the supported way
a2a_client = await create_a2a_client(
base_url=api_base,
extra_headers=agent_extra_headers,
) Type guard
from typing import Any, TypeGuard
def is_litellm_managed_client(client: Any) -> TypeGuard[Any]:
"""Narrows to clients created by create_a2a_client, which carry the
shared litellm httpx client and support localhost-URL retries."""
return getattr(client, '_litellm_httpx_client', None) is not None Try / catch
try:
resp = await asend_message(a2a_client=my_client, request=req, api_base=api_base)
except RuntimeError as e:
if 'create_a2a_client' in str(e):
my_client = await create_a2a_client(base_url=api_base)
resp = await asend_message(a2a_client=my_client, request=req, api_base=api_base)
else:
raise Prevention
- Treat create_a2a_client as the only supported client factory for litellm A2A calls
- Push custom httpx needs (timeout, headers) through create_a2a_client's options
- Regression-test your retry path, not just the happy path, when swapping clients
When it happens
Trigger: Passing a self-built a2a-sdk client (e.g. ClientBuilder(...).build()) to asend_message/asend_message_streaming, then hitting the localhost-card retry path: the rewritten card cannot be used because no LiteLLM httpx client is attached.
Common situations: Custom client tuning (timeouts, proxies, custom auth) leading teams to hand-roll the client; code written against older litellm versions that accepted arbitrary clients.
Related errors
- A2A send_message failed: no response received after retry…
- A2A send_message_streaming failed: no response received…
- Cannot retry A2A localhost URL fix: no agent card is…
- A2A SDK is required for localhost retry handling. Install…
- A2A send_message failed: no response received from agent.
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/7388ac8df0aa10ba.
Report an issue: GitHub.
Appendix: source
Thrown at litellm/a2a_protocol/exception_mapping_utils.py:210
request_type: Final = "streaming " if is_streaming else ""
verbose_logger.warning(
"A2A %srequest to '%s' failed: %s. Agent card contains localhost/internal URL. Retrying with base_url '%s'.",
request_type,
error.localhost_url,
error.original_error,
error.base_url,
)
# Fix the agent card URL
set_agent_card_url(agent_card, error.base_url)
# Reuse the httpx client and call context LiteLLM attached at creation, since the
# context carries this agent's trace-id/auth headers. Only clients built by
# ``create_a2a_client`` have them; an externally-supplied client cannot be retried.
httpx_client: Final = getattr(a2a_client, "_litellm_httpx_client", None)
if httpx_client is None:
raise RuntimeError(
"Cannot retry A2A localhost URL fix: the client was not created by "
"create_a2a_client, so no LiteLLM httpx client is attached."
)
new_client: Final = await create_client( # pyright: ignore[reportOptionalCall]
agent_card,
client_config=ClientConfig( # pyright: ignore[reportOptionalCall]
httpx_client=httpx_client,
streaming=is_streaming,
),
)
new_client._litellm_httpx_client = httpx_client
new_client._litellm_call_context = getattr( # pyright: ignore[reportAttributeAccessIssue] # LiteLLM-owned stash
a2a_client, "_litellm_call_context", None
)
new_client._litellm_agent_card = agent_card
return new_client
View on GitHub (pinned to 77b7c6c40c)