{"record":{"id":"2eb3f13f053d335b","repo":"PrefectHQ/fastmcp","slug":"error-reading-resource-uri-r","errorCode":null,"errorMessage":"Error reading resource {uri!r}","messagePattern":"Error reading resource (.+?)","errorType":"exception","errorClass":"ResourceError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/server/server.py","lineNumber":1653,"sourceCode":"                        )\n                        raise\n                    except MCPError:\n                        logger.exception(f\"Error reading resource {uri!r}\")\n                        raise\n                    except Exception as e:\n                        logger.exception(f\"Error reading resource {uri!r}\")\n                        # Handle actionable errors that should reach the LLM\n                        if get_http_status_code(e) == 429:\n                            raise ResourceError(\n                                \"Rate limited by upstream API, please retry later\"\n                            ) from e\n                        if is_timeout_error(e):\n                            raise ResourceError(\n                                \"Upstream request timed out, please retry\"\n                            ) from e\n                        # Standard masking logic\n                        if self._mask_error_details:\n                            raise ResourceError(\n                                f\"Error reading resource {uri!r}\"\n                            ) from e\n                        raise ResourceError(\n                            f\"Error reading resource {uri!r}: {e}\"\n                        ) from e\n\n                # Try templates (transforms + auth via get_resource_template)\n                template = await self.get_resource_template(uri, version=version)\n                if template is None:\n                    if version is None:\n                        raise NotFoundError(f\"Unknown resource: {uri!r}\")\n                    raise NotFoundError(\n                        f\"Unknown resource: {uri!r} version {version!r}\"\n                    )\n                span.set_attributes(template.get_span_attributes())\n                params = template.matches(uri)\n                assert params is not None\n","sourceCodeStart":1635,"sourceCodeEnd":1671,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/server/server.py#L1635-L1671","documentation":"FastMCP raises ResourceError(\"Error reading resource {uri!r}\") when reading a resource raised an unexpected exception and error masking is enabled (`mask_error_details=True`). The original exception is hidden and chained as __cause__; details remain in server logs via logger.exception. It is the library's way of preventing internal details from leaking to LLM clients.","triggerScenarios":"Calling `await server.read_resource(uri)` (directly or via `_on_read_resource`/client `read_resource`) where the concrete resource's `_read()` raises a non-FastMCP, non-MCPError exception (e.g. OSError, HTTP error that isn't 429 or a timeout) and the server was constructed with mask_error_details=True.","commonSituations":"Resource functions hitting a filesystem/DB/network failure in production with error masking on; developers confused why the client shows a generic message while logs hold the real cause; environments where an upstream API URL/key is misconfigured.","solutions":["Check the server logs for 'Error reading resource <uri>' with the full traceback to find the underlying exception.","Fix the root cause in the resource handler (file path, network endpoint, credentials).","During debugging, disable masking (mask_error_details=False) so the client message includes the underlying error text.","If the failure is expected, raise a FastMCPError/ResourceError subclass from the handler with a client-appropriate message so it passes through unmasked."],"exampleFix":"// before: server = FastMCP(mask_error_details=True)  # client sees only \"Error reading resource 'file:///data.csv'\"\n// after: server = FastMCP(mask_error_details=False)  # or fix handler:\n# before\ndef load():\n    return open(MISSING_PATH).read()\n# after\n@resource(\"data://csv\")\ndef load():\n    try:\n        return open(DATA_PATH).read()\n    except FileNotFoundError as e:\n        raise ResourceError(\"CSV data file is not yet generated\") from e","handlingStrategy":"try-catch","validationCode":"// ensure the resource exists before reading\nresources = await client.list_resources()\nassert any(str(r.uri) == uri for r in resources), f\"{uri} not exposed by server\"","typeGuard":null,"tryCatchPattern":"try:\n    result = await client.read_resource(uri)\nexcept ResourceError as e:\n    if 'Error reading resource' in str(e):\n        logger.error(f\"masked resource failure for {uri}; check server logs\", exc_info=e)\n        raise","preventionTips":["Keep mask_error_details=False in dev so failures are self-explanatory.","Raise typed FastMCP errors from handlers for expected failures so they bypass masking.","Monitor server logs, which always carry the unmasked traceback.","Wrap risky I/O in handlers with specific exception handling."],"tags":["mcp","resource","error-masking","python"],"backgroundTag":"error-details-masked","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}