PrefectHQ/fastmcp · error · ResourceError
Error reading resource {uri!r}: {e}
Error message
Error reading resource {uri!r}: {e} What it means
FastMCP raises ResourceError("Error reading resource {uri!r}: {e}") when a resource read fails with an unexpected exception and error masking is disabled. The underlying exception text is appended so the caller (often an LLM) can see what went wrong; the original exception is chained as __cause__.
Source
Thrown at fastmcp_slim/fastmcp/server/server.py:1656
logger.exception(f"Error reading resource {uri!r}")
raise
except Exception as e:
logger.exception(f"Error reading resource {uri!r}")
# Handle actionable errors that should reach the LLM
if get_http_status_code(e) == 429:
raise ResourceError(
"Rate limited by upstream API, please retry later"
) from e
if is_timeout_error(e):
raise ResourceError(
"Upstream request timed out, please retry"
) from e
# Standard masking logic
if self._mask_error_details:
raise ResourceError(
f"Error reading resource {uri!r}"
) from e
raise ResourceError(
f"Error reading resource {uri!r}: {e}"
) from e
# Try templates (transforms + auth via get_resource_template)
template = await self.get_resource_template(uri, version=version)
if template is None:
if version is None:
raise NotFoundError(f"Unknown resource: {uri!r}")
raise NotFoundError(
f"Unknown resource: {uri!r} version {version!r}"
)
span.set_attributes(template.get_span_attributes())
params = template.matches(uri)
assert params is not None
# Path-security screening: reject traversal / absolute-path /
# null-byte payloads in extracted parameter values BEFORE the
# handler runs. This is the single chokepoint for everyView on GitHub (pinned to 1f02114297)
Solutions
- Read the ': {e}' suffix — it names the real underlying error; fix that in the resource function.
- Ensure required env/config for the resource (paths, URLs, keys) are set.
- If the message could leak secrets, enable mask_error_details=True or raise ResourceError yourself with a sanitized message.
- Add retry/validation inside the handler for transient upstream failures.
Example fix
// before
@resource("api://user")
def get_user():
return requests.get(URL).json() # raises ConnectionError -> ResourceError("...: ConnectionError...")
// after
@resource("api://user")
def get_user():
try:
return requests.get(URL, timeout=10).json()
except requests.RequestException as e:
raise ResourceError(f"User API unavailable: {e}") from e Defensive patterns
Strategy: try-catch
Try / catch
try:
result = await client.read_resource(uri)
except ResourceError as e:
logger.error(f"Resource {uri} failed: {e}") # suffix names the root cause
raise Prevention
- Fix the root-cause exception named after ': ' in the message.
- Validate handler inputs and config (paths, env vars) at startup.
- Add timeouts and error handling around handler I/O.
- Enable masking in production if messages may leak internals.
When it happens
Trigger: `await server.read_resource(uri)` where the resource's `_read()` raises a plain Exception (not FastMCPError/MCPError, not a 429, not a timeout) on a server constructed without mask_error_details (default).
Common situations: Development/debugging where masking is off; resource handlers with bugs (bad paths, missing env vars, unparsed responses); integration tests surfacing handler exceptions verbatim.
Related errors
- Error reading resource {uri!r}
- The client negotiated a modern protocol era (server/discover
- logging/setLevel is not available on MCP 2026-07-28 connecti
- Unsupported content type: {type(item)}
- Remote server returned empty content for {parameterized_uri}
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/c3237d52ad6ca6cf.
Report an issue: GitHub.