{"record":{"id":"e6c7166ecfaa73cc","repo":"PrefectHQ/fastmcp","slug":"upstream-request-timed-out-please-retry","errorCode":null,"errorMessage":"Upstream request timed out, please retry","messagePattern":"Upstream request timed out, please retry","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"warning","filePath":"fastmcp_slim/fastmcp/server/server.py","lineNumber":1549,"sourceCode":"                    if (\n                        isinstance(e, MCPError)\n                        and e.error.code == MISSING_REQUIRED_CLIENT_CAPABILITY\n                    ):\n                        logger.debug(\n                            \"Tool %r requires a client capability the client did \"\n                            \"not declare\",\n                            name,\n                        )\n                        raise\n                    logger.exception(f\"Error calling tool {name!r}\")\n                    # Handle actionable errors that should reach the LLM\n                    # even when masking is enabled\n                    if get_http_status_code(e) == 429:\n                        raise ToolError(\n                            \"Rate limited by upstream API, please retry later\"\n                        ) from e\n                    if is_timeout_error(e):\n                        raise ToolError(\n                            \"Upstream request timed out, please retry\"\n                        ) from e\n                    # Standard masking logic\n                    if self._mask_error_details:\n                        raise ToolError(f\"Error calling tool {name!r}\") from e\n                    raise ToolError(f\"Error calling tool {name!r}: {e}\") from e\n\n    async def read_resource(\n        self,\n        uri: str,\n        *,\n        version: VersionSpec | None = None,\n        run_middleware: bool = True,\n    ) -> ResourceResult:\n        \"\"\"Read a resource by URI.\n\n        This is the public API for reading resources. By default, middleware is applied.\n        Checks concrete resources first, then templates.","sourceCodeStart":1531,"sourceCodeEnd":1567,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/server/server.py#L1531-L1567","documentation":"call_tool's exception handler converts any tool exception matching is_timeout_error into ToolError('Upstream request timed out, please retry'). Like the 429 case, timeouts are treated as actionable and reach the client even when _mask_error_details is on, signaling a transient failure worth retrying.","triggerScenarios":"A tool's handler makes an upstream network call (HTTP, DB, socket) that times out — httpx.TimeoutException, asyncio.TimeoutError, socket.timeout, etc. — and the exception escapes tool._run.","commonSituations":"Upstream API slow or degraded; too-short client timeouts in the tool's HTTP client; large payloads/slow queries; network partitions between the MCP server and its dependencies.","solutions":["Retry the tool call — the error is transient by design","Increase the timeout in the tool's internal HTTP/DB client configuration","Add circuit-breaking/deadline budgets inside the tool and partial results on timeout","Check upstream service health/status pages","Move long work behind an async job pattern instead of blocking the tool call"],"exampleFix":"// inside the tool: before\ndef fetch():\n    return httpx.get(url)\n// after\ndef fetch():\n    return httpx.get(url, timeout=httpx.Timeout(30.0))","handlingStrategy":"retry","validationCode":null,"typeGuard":"def is_timeout(e: BaseException) -> bool:\n    return isinstance(e, ToolError) and 'timed out' in str(e)","tryCatchPattern":"import asyncio\nfor attempt in range(3):\n    try:\n        return await client.call_tool('my_tool', args)\n    except ToolError as e:\n        if 'timed out' not in str(e):\n            raise\n        await asyncio.sleep(2 ** attempt)\nraise RuntimeError('tool kept timing out')","preventionTips":["Set generous but bounded timeouts in tool HTTP clients","Use bounded retries with exponential backoff","Monitor upstream latency and alert on degradation","Prefer async job patterns for work that can exceed request deadlines"],"tags":["timeout","network","tools","retry"],"backgroundTag":"upstream-timeout","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}