{"record":{"id":"a89bed2fd9aa99dc","repo":"BerriAI/litellm","slug":"agent-card-contains-localhost-internal-url-local","errorCode":null,"errorMessage":"Agent card contains localhost/internal URL '{localhost_url}'. Retrying with base URL '{base_url}'.","messagePattern":"Agent card contains localhost/internal URL '(.+?)'\\. Retrying with base URL '(.+?)'\\.","errorType":"exception","errorClass":"A2ALocalhostURLError","httpStatus":503,"severity":"warning","filePath":"litellm/a2a_protocol/exception_mapping_utils.py","lineNumber":130,"sourceCode":"    Returns:\n        A mapped LiteLLM A2A exception\n\n    Raises:\n        A2ALocalhostURLError: If the error is a connection error to a localhost URL\n        A2AConnectionError: If the error is a general connection error\n        A2AAgentCardError: If the error is related to agent card issues\n        A2AError: For other A2A-related errors\n    \"\"\"\n    error_str: Final = str(original_exception)\n\n    # Check for localhost URL connection error (special case - retryable)\n    if (\n        card_url\n        and api_base\n        and A2AExceptionCheckers.is_localhost_url(card_url)\n        and A2AExceptionCheckers.is_connection_error(error_str)\n    ):\n        raise A2ALocalhostURLError(\n            localhost_url=card_url,\n            base_url=api_base,\n            original_error=original_exception,\n            model=model,\n        )\n\n    # Check for agent card errors\n    if A2AExceptionCheckers.is_agent_card_error(error_str):\n        raise A2AAgentCardError(\n            message=error_str,\n            url=api_base,\n            model=model,\n        )\n\n    # Check for general connection errors\n    if A2AExceptionCheckers.is_connection_error(error_str):\n        raise A2AConnectionError(\n            message=error_str,","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/a2a_protocol/exception_mapping_utils.py#L112-L148","documentation":"An A2A agent serves a self-describing 'agent card' whose URL field may point at localhost/127.0.0.1 or an internal address. When LiteLLM follows the card's advertised URL and gets a connection error, map_a2a_exception classifies it as A2ALocalhostURLError and the retry handler rewrites the card URL back to your original api_base and resends, logging this warning. The warning therefore marks a recovered-by-retry condition, very common with containerized agents that hardcode localhost.","triggerScenarios":"await asend_message(api_base='http://agent-svc:10001', ...) where the fetched card advertises 'http://localhost:10001'; any A2A call where the card URL is only routable inside the agent's own network namespace (Docker, K8s, NAT).","commonSituations":"Docker Compose / Kubernetes deployments of A2A agents (LangGraph Platform etc.) that publish localhost in .well-known/agent-card.json; local dev against a port-forwarded remote agent.","solutions":["Let LiteLLM's built-in retry handle it — it already resends against your api_base; treat the log as a warning, not a failure","Fix the agent so its card advertises an externally reachable URL (most agent frameworks expose a PUBLIC_URL / host env for this)","Fix DNS/network so the advertised URL resolves from where litellm runs"],"exampleFix":"# agent env — before\nA2A_HOST=localhost  # card advertises http://localhost:10001\n\n# agent env — after\nA2A_HOST=agent-svc  # card advertises http://agent-svc:10001, routable from litellm","handlingStrategy":"retry","validationCode":"from urllib.parse import urlparse\n\n\ndef is_internal_url(url: str | None) -> bool:\n    if not url:\n        return False\n    host = (urlparse(url).hostname or '').lower()\n    return (\n        host in {'localhost', '127.0.0.1', '0.0.0.0', '::1'}\n        or host.startswith('10.')\n        or host.startswith('192.168.')\n        or host.startswith('172.')\n    )\n\n\n# pre-flight: fetch and sanitize the card before first send\ncard = await aget_agent_card(base_url=api_base)\nif is_internal_url(getattr(card, 'url', None)):\n    card.url = api_base  # rewrite so no failed attempt is needed","typeGuard":null,"tryCatchPattern":"from litellm.a2a_protocol.exception_mapping_utils import (\n    A2ALocalhostURLError,  # exported via the a2a_protocol package\n)\n\ntry:\n    resp = await asend_message(a2a_client=client, request=req, api_base=api_base)\nexcept A2ALocalhostURLError:\n    # library already retried once internally; a second escape means the\n    # agent card itself must be fixed\n    raise RuntimeError(f'Agent card advertises an unreachable URL for {api_base}')","preventionTips":["Set the agent's advertised/public URL env to a routable address in containerized deployments","At startup, fetch the agent card and verify its URL is reachable from the litellm host","Always pass api_base so litellm's localhost retry path stays available"],"tags":["a2a","agent-card","localhost","docker","kubernetes","retry"],"backgroundTag":"service-advertises-localhost-url","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}