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
- Check the upstream endpoint is reachable and fast (curl the same URL)
- Increase the httpx.Timeout on the AsyncClient you pass to FastMCPProvider/OpenAPIProvider
- 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
- Set explicit generous httpx.Timeout on the client passed to the provider
- Monitor upstream latency and alert before timeouts
- Use connect/read timeouts tuned to the slowest endpoint
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
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- HTTP error {response.status_code}: {response.reason_phrase}
- Request error ({type(exc).__name__}): {exc!s}
- User server did not start on port {mcp_port}
- Unexpected authorization response: {response.status_code}
- str(e)
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/690673fee70a6429.
Report an issue: GitHub.