PrefectHQ/fastmcp · error · ValueError

HTTP request timed out ({type(exc).__name__})

Error message

HTTP request timed out ({type(exc).__name__})

What it means

FastMCP's OpenAPI proxy sends upstream HTTP requests via httpx and deliberately wraps timeout exceptions (httpx.TimeoutException subclasses like ConnectTimeout/ReadTimeout) into ValueError('HTTP request timed out (...)') so callers get a consistent message while the original exception is chained. It is raised from _send_request, used by tool run and resource read paths.

Source

Thrown at fastmcp_slim/fastmcp/server/providers/openapi/components.py:86

    try:
        error_data = response.json()
        error_message += f" - {error_data}"
    except (json.JSONDecodeError, ValueError):
        if response.text:
            error_message += f" - {response.text}"
    raise ValueError(error_message)


async def _send_request(
    client: httpx2.AsyncClient,
    request: httpx2.Request,
) -> httpx2.Response:
    """Send a request while preserving transitional legacy-client errors."""
    try:
        return await client.send(request)
    except Exception as exc:
        if is_timeout_error(exc):
            raise ValueError(f"HTTP request timed out ({type(exc).__name__})") from exc
        if is_request_error(exc):
            raise ValueError(f"Request error ({type(exc).__name__}): {exc!s}") from exc
        raise


def _extract_mime_type_from_route(route: HTTPRoute) -> str:
    """Extract the primary MIME type from an HTTPRoute's response definitions.

    Looks for the first successful response (2xx) and returns its content type.
    Prefers JSON-compatible types when multiple are available.
    Falls back to "application/json" when no response content type is declared.
    """
    if not route.responses:
        return _DEFAULT_MIME_TYPE

    # Priority order for success status codes
    success_codes = ["200", "201", "202", "204"]

View on GitHub (pinned to 1f02114297)

Solutions

  1. Check the upstream endpoint is reachable and fast (curl the same URL)
  2. Increase the httpx.Timeout on the AsyncClient you pass to FastMCPProvider/OpenAPIProvider
  3. Catch the ValueError and implement app-level retry/fallback

Example fix

// before
client = httpx.AsyncClient()
// after
client = httpx.AsyncClient(timeout=httpx.Timeout(30.0, connect=10.0))
Defensive patterns

Strategy: retry

Validate before calling

import httpx
async def reachable(client: httpx.AsyncClient, url: str) -> bool:
    try:
        await client.get(url, timeout=5.0)
        return True
    except httpx.TimeoutException:
        return False

Try / catch

try:
    result = await tool.run(args)
except ValueError as e:
    if 'timed out' in str(e):
        result = await retry_with_backoff(tool.run, args)
    else:
        raise

Prevention

When it happens

Trigger: Calling an OpenAPI-derived tool or resource whose upstream backend does not respond before the httpx client's timeout expires (connect or read timeout).

Common situations: Slow upstream REST API, wrong/undebuggable host in the servers URL, backend blocked by firewall, timeout configured too low in the custom AsyncClient passed to the provider.

Understand the failure class

Related errors


AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29). Data as JSON: /api/errors/690673fee70a6429. Report an issue: GitHub.