microsoft/semantic-kernel · error · FunctionExecutionException

The request URI host '{host}' is not allowed: DNS resolution

Error message

The request URI host '{host}' is not allowed: DNS resolution failed. The request is blocked as a precaution to prevent potential access to private network addresses.

What it means

Thrown when DNS resolution itself raised OSError or ValueError (NXDOMAIN, DNS server unreachable, transient resolver failure, or a custom resolver returning a non-IP string). Blocked preemptively because a resolution failure could mask a private/internal address.

Source

Thrown at python/semantic_kernel/connectors/openapi_plugin/server_url_validator.py:165

        )

    for address in addresses:
        _ensure_public_address(parsed_url.geturl(), address)


async def _resolve_host(
    host: str,
    dns_resolver: DnsResolver | None,
) -> list[ipaddress.IPv4Address | ipaddress.IPv6Address]:
    try:
        if dns_resolver:
            resolved_addresses = await dns_resolver(host)
            return [ipaddress.ip_address(address) for address in resolved_addresses]

        loop = asyncio.get_running_loop()
        addr_info = await loop.getaddrinfo(host, None, type=socket.SOCK_STREAM)
    except (OSError, ValueError) as exc:
        raise FunctionExecutionException(
            f"The request URI host '{host}' is not allowed: DNS resolution failed. "
            "The request is blocked as a precaution to prevent potential access to private network addresses."
        ) from exc

    addresses: list[ipaddress.IPv4Address | ipaddress.IPv6Address] = []
    seen_addresses: set[str] = set()
    for family, _, _, _, sockaddr in addr_info:
        if family not in (socket.AF_INET, socket.AF_INET6):
            continue
        address = ipaddress.ip_address(sockaddr[0])
        address_string = str(address)
        if address_string not in seen_addresses:
            addresses.append(address)
            seen_addresses.add(address_string)
    return addresses


def _ensure_public_address(url: str, address: ipaddress.IPv4Address | ipaddress.IPv6Address) -> None:

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Confirm the hostname resolves in your environment (nslookup/dig)
  2. Check DNS server connectivity and retries
  3. If transient, retry the request
  4. If the host is legitimately trusted, add its base URL to allowed_base_urls to skip DNS checks
  5. Ensure a custom dns_resolver returns valid IP address strings and does not raise on normal input
Defensive patterns

Strategy: retry

Validate before calling

import socket

def host_resolves(host: str) -> bool:
    try:
        socket.getaddrinfo(host, None, type=socket.SOCK_STREAM)
        return True
    except OSError:
        return False

if not host_resolves(urlparse(url).hostname):
    # may be transient; retry or add to allowed_base_urls if trusted
    ...

Try / catch

import asyncio
from semantic_kernel.exceptions.function_exceptions import FunctionExecutionException

for attempt in range(3):
    try:
        await validate_server_url(url, options)
        break
    except FunctionExecutionException as e:
        if 'DNS resolution failed' in str(e) and attempt < 2:
            await asyncio.sleep(2 ** attempt)
            continue
        raise

Prevention

When it happens

Trigger: getaddrinfo raises OSError for a non-existent domain or unreachable DNS server; a custom dns_resolver raises; or a returned value is not a valid IP (ValueError on ipaddress.ip_address).

Common situations: DNS server down or unreachable; hostname does not exist; network partition/firewall blocking DNS; custom resolver implementation error; transient resolver hiccup.

Understand the failure class

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/5ca206311fcc6fc9. Report an issue: GitHub.