{"record":{"id":"690673fee70a6429","repo":"PrefectHQ/fastmcp","slug":"http-request-timed-out-type-exc-name","errorCode":null,"errorMessage":"HTTP request timed out ({type(exc).__name__})","messagePattern":"HTTP request timed out \\((.+?)\\)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/server/providers/openapi/components.py","lineNumber":86,"sourceCode":"    try:\n        error_data = response.json()\n        error_message += f\" - {error_data}\"\n    except (json.JSONDecodeError, ValueError):\n        if response.text:\n            error_message += f\" - {response.text}\"\n    raise ValueError(error_message)\n\n\nasync def _send_request(\n    client: httpx2.AsyncClient,\n    request: httpx2.Request,\n) -> httpx2.Response:\n    \"\"\"Send a request while preserving transitional legacy-client errors.\"\"\"\n    try:\n        return await client.send(request)\n    except Exception as exc:\n        if is_timeout_error(exc):\n            raise ValueError(f\"HTTP request timed out ({type(exc).__name__})\") from exc\n        if is_request_error(exc):\n            raise ValueError(f\"Request error ({type(exc).__name__}): {exc!s}\") from exc\n        raise\n\n\ndef _extract_mime_type_from_route(route: HTTPRoute) -> str:\n    \"\"\"Extract the primary MIME type from an HTTPRoute's response definitions.\n\n    Looks for the first successful response (2xx) and returns its content type.\n    Prefers JSON-compatible types when multiple are available.\n    Falls back to \"application/json\" when no response content type is declared.\n    \"\"\"\n    if not route.responses:\n        return _DEFAULT_MIME_TYPE\n\n    # Priority order for success status codes\n    success_codes = [\"200\", \"201\", \"202\", \"204\"]\n","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/server/providers/openapi/components.py#L68-L104","documentation":"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.","triggerScenarios":"Calling an OpenAPI-derived tool or resource whose upstream backend does not respond before the httpx client's timeout expires (connect or read timeout).","commonSituations":"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.","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"],"exampleFix":"// before\nclient = httpx.AsyncClient()\n// after\nclient = httpx.AsyncClient(timeout=httpx.Timeout(30.0, connect=10.0))","handlingStrategy":"retry","validationCode":"import httpx\nasync def reachable(client: httpx.AsyncClient, url: str) -> bool:\n    try:\n        await client.get(url, timeout=5.0)\n        return True\n    except httpx.TimeoutException:\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    result = await tool.run(args)\nexcept ValueError as e:\n    if 'timed out' in str(e):\n        result = await retry_with_backoff(tool.run, args)\n    else:\n        raise","preventionTips":["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"],"tags":["network","http","timeout","openapi"],"backgroundTag":"http-request-timeout","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}