microsoft/semantic-kernel · error · FunctionExecutionException

The request URI '{url}' is not allowed because it is not a v

Error message

The request URI '{url}' is not allowed because it is not a valid absolute URI.

What it means

`validate_server_url` is the SSRF guard. It first tries `_parse_absolute_url(url)`; if that raises `ValueError` (the URL is not a valid absolute URI), it is wrapped as `FunctionExecutionException` with this message. This is the earliest validation step — before allowlist, scheme, and DNS checks.

Source

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

    allow_private_network_access: bool = False

    def model_post_init(self, __context: Any) -> None:
        """Validate configured allowed base URLs."""
        for allowed_base_url in self.allowed_base_urls:
            _parse_absolute_url(allowed_base_url, option_name="allowed_base_urls")


async def validate_server_url(
    url: str,
    options: ServerUrlValidationOptions | None = None,
    dns_resolver: DnsResolver | None = None,
) -> None:
    """Validate a fully resolved OpenAPI operation URL against the supplied policy."""
    options = options or ServerUrlValidationOptions()
    try:
        parsed_url = _parse_absolute_url(url)
    except ValueError as exc:
        raise FunctionExecutionException(
            f"The request URI '{url}' is not allowed because it is not a valid absolute URI."
        ) from exc

    if _matches_allowed_base_url(parsed_url, options.allowed_base_urls):
        return

    if options.allowed_base_urls:
        raise FunctionExecutionException(
            f"The request URI '{url}' is not allowed. It does not match any of the allowed base URLs."
        )

    if parsed_url.scheme.lower() != DEFAULT_ALLOWED_SCHEME:
        raise FunctionExecutionException(
            f"The request URI scheme '{parsed_url.scheme}' is not allowed. "
            f"Only '{DEFAULT_ALLOWED_SCHEME}' is permitted by default. "
            "To allow this URL, add it to server_url_validation_allowed_base_urls."
        )

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Provide `server_url_override` (a full absolute URL) in `OpenAPIFunctionExecutionParameters` so the resolved operation URL is absolute.
  2. Ensure the spec's `servers` entries are absolute URLs, or pass `document_uri` so `api_host_url` can be derived.
  3. Log the resolved URL before invocation to see what is being validated.
  4. If the URL comes from path templating, verify all path/variable substitutions produce a well-formed absolute URL.

Example fix

# before
params = OpenAPIFunctionExecutionParameters()  # spec has only servers: [{url: '/'}]
await runner.run_operation(op, args, options)  # resolved url '/' -> raises 1499

# after
params = OpenAPIFunctionExecutionParameters(server_url_override="https://api.example.com")
await runner.run_operation(op, args, options)
Defensive patterns

Strategy: validation

Validate before calling

from urllib.parse import urlparse
from semantic_kernel.connectors.openapi_plugin.server_url_validator import (
    validate_server_url, ServerUrlValidationOptions,
)

def ensure_absolute(url: str) -> str:
    p = urlparse(url)
    if not p.scheme or not p.netloc:
        raise ValueError(f"Resolved URL is not absolute: {url!r}")
    return url

resolved = ensure_absolute(operation.build_operation_url(arguments, override, host))
await validate_server_url(resolved, options)

Type guard

def is_absolute_url(value: str) -> bool:
    p = urlparse(value)
    return bool(p.scheme in ("http", "https") and p.netloc)

Try / catch

from semantic_kernel.exceptions import FunctionExecutionException

try:
    await runner.run_operation(op, args, options)
except FunctionExecutionException as e:
    if "not a valid absolute URI" in str(e):
        # supply server_url_override / document_uri, then retry
        params = OpenAPIFunctionExecutionParameters(server_url_override="https://api.example.com")
        raise
    raise

Prevention

When it happens

Trigger: Passing a URL to an OpenAPI operation whose final resolved form is not absolute (no scheme, no host, or malformed) — e.g. a server URL that was a relative path with no base, an empty string, or a value with invalid characters. Also if `server_url_override` produces a relative URL after substitution.

Common situations: Spec defines only a relative server (`url: /`) and no `api_host_url` / override was supplied; a path-template substitution produced a malformed URL; `server_url_override` set to a non-absolute value that slipped past `model_post_init`; templated server variables left unsubstituted.

Related errors


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