PrefectHQ/fastmcp · error · AuthorizationError
Authorization failed for resource '{uri}': not found or not
Error message
Authorization failed for resource '{uri}': not found or not authorized What it means
For resources/read, AuthMiddleware resolves the component via `get_resource(uri, version)` and, failing that, `get_resource_template(uri, version)`; when both return None it raises this AuthorizationError. Both 'does not exist' and 'exists but component-level auth hid it' map to the same deliberately ambiguous message so resource existence is not disclosed to unauthorized callers.
Source
Thrown at fastmcp_slim/fastmcp/server/middleware/authorization.py:319
"Denying access for security."
)
raise AuthorizationError(
f"Authorization failed for resource '{uri}': missing context"
)
# get_resource/get_resource_template return None both when the resource
# does not exist and when component-level auth denied access, so the two
# cases are indistinguishable here. Keep the message ambiguous to avoid
# disclosing existence of resources the caller is not authorized to see.
version = _requested_version(context.message.meta)
component = await fastmcp.fastmcp.get_resource(str(uri), version=version)
if component is None:
component = await fastmcp.fastmcp.get_resource_template(
str(uri),
version=version,
)
if component is None:
raise AuthorizationError(
f"Authorization failed for resource '{uri}': "
"not found or not authorized"
)
# Global auth check
token = get_access_token()
ctx = AuthContext(token=token, component=component)
authorized, missing = await run_auth_checks_with_shortfall(self.auth, ctx)
if not authorized:
if missing:
missing = self._chain_shortfall(missing, ctx, fastmcp.fastmcp)
raise InsufficientScopeError(
missing,
message=(
f"Authorization failed for resource '{uri}': "
f"insufficient scope (required: {', '.join(missing)})"
),
)View on GitHub (pinned to 1f02114297)
Solutions
- List resources/templates as the authorized client (`session.list_resources()` / `list_resource_templates()`) and use an exact returned URI.
- Check the URI against the template pattern; supply parameters in the expected format (e.g. 'data://42' not 'data?id=42').
- If the component requires auth, grant the caller's token the configured scopes/roles so the lookup stops being filtered.
- Verify the requested version in _meta exists, or omit it to get the default variant.
Example fix
# before
await client.read_resource('config://app') # server only has 'config://{env}'
# after
templates = await client.list_resource_templates()
uri = templates[0].uri_template.replace('{env}', 'prod')
await client.read_resource(uri) Defensive patterns
Strategy: validation
Validate before calling
uris = {str(r.uri) for r in await client.list_resources()}
uris |= {t.uri_template for t in await client.list_resource_templates()}
assert uri in uris, 'URI not visible to this caller; check format and auth' Try / catch
from fastmcp.exceptions import AuthorizationError
try:
res = await client.read_resource(uri)
except AuthorizationError as e:
if 'not found or not authorized' in str(e):
known = await client.list_resources()
logger.warning('URI %s unavailable; known: %s', uri, [str(r.uri) for r in known])
else:
raise Prevention
- Copy URIs from list_resources/list_resource_templates responses instead of hand-writing them.
- Match resource template URI format exactly (path parameters, scheme).
- Check component-level auth config when a resource exists but is denied.
- Avoid requesting _meta versions that may not exist; prefer defaults.
When it happens
Trigger: Client requests a URI that matches no registered resource or resource template, a URI that doesn't match the template pattern (e.g. wrong parameter format for 'data://{id}'), a version requested via _meta with no matching variant, or component-level auth denying this caller so lookup returns None.
Common situations: URI escaping/format mismatches against a resource template (missing scheme, query instead of path parameter); client caching a URI from a renamed resource; versioned component variants removed; resource hidden by auth policy for this token.
Related errors
- Authorization failed for tool '{tool_name}': not found or no
- Authorization failed for tool '{tool_name}': insufficient pe
- Authorization failed for resource '{uri}': missing context
- Authorization failed for resource '{uri}': insufficient perm
- Authorization failed for tool '{tool_name}': missing context
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/38a00bfd1a164601.
Report an issue: GitHub.