PrefectHQ/fastmcp · error · InsufficientScopeError
Authorization failed for resource '{uri}': insufficient scop
Error message
Authorization failed for resource '{uri}': insufficient scope (required: {', '.join(missing)}) What it means
The resource/template was found but the global auth checks returned unauthorized with a non-empty shortfall of missing scopes. The middleware raises InsufficientScopeError naming the required scopes (post _chain_shortfall) so clients can perform scope-upgrade flows (RFC 6750 insufficient_scope).
Source
Thrown at fastmcp_slim/fastmcp/server/middleware/authorization.py:331
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)})"
),
)
raise AuthorizationError(
f"Authorization failed for resource '{uri}': insufficient permissions"
)
return await call_next(context)
async def on_list_resource_templates(
self,
context: MiddlewareContext[mt.ListResourceTemplatesRequest],
call_next: CallNext[
mt.ListResourceTemplatesRequest, Sequence[ResourceTemplate]
],View on GitHub (pinned to 1f02114297)
Solutions
- Re-obtain a token containing every scope listed after 'required:' in the message.
- Adjust the OAuth client's requested scopes or provider config so issued tokens include them.
- If the resource's scope requirements are wrong, update its auth configuration (requires_scopes / auth policy) in code.
- Validate claim mapping (SCOPE claim, audience) between the identity provider and the FastMCP auth server.
Example fix
# before
token = get_token(scopes=['data:read'])
await client.read_resource('pii://users/1') # requires pii:read
# after
token = get_token(scopes=['data:read', 'pii:read'])
await client.read_resource('pii://users/1') Defensive patterns
Strategy: try-catch
Validate before calling
claims = decode_jwt(token)
have = set(claims.get('scope', '').split())
assert {'data:read', 'pii:read'}.issubset(have), 'token missing resource scopes' Try / catch
from fastmcp.exceptions import InsufficientScopeError
try:
res = await client.read_resource(uri)
except InsufficientScopeError as e:
missing = getattr(e, 'missing_scopes', None) or parse_scopes(str(e))
token = await auth_provider.refresh_with_scopes(missing)
client.set_auth(BearerAuth(token))
res = await client.read_resource(uri) Prevention
- Grant tokens all scopes required by protected resources at issuance time.
- Implement an insufficient_scope upgrade flow rather than failing hard.
- Keep resource requires_scopes config and provider scope catalog in sync.
- Re-test tokens after changing auth providers or scope names.
When it happens
Trigger: resources/read for a registered resource whose required scopes (resource-level or global policy) are not all present in the access token — e.g. token has 'data:read' but the resource requires 'data:read' plus 'pii:read'.
Common situations: OAuth tokens downscoped or issued before new scopes were added to the resource; scope naming drift after switching auth providers; service accounts missing newly-required scopes; test tokens without production scopes.
Related errors
- Authorization failed for tool '{tool_name}': insufficient sc
- Assertion missing required scopes: {sorted(missing)}
- OAuth client not found - cached credentials may be stale
- OAuth server rejected the static client credentials. Verify
- Assertion must include exp claim
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/591bc19d4a8ae501.
Report an issue: GitHub.