PrefectHQ/fastmcp · error · RuntimeError

Claim '{self.claim_name}' not found in access token. Availab

Error message

Claim '{self.claim_name}' not found in access token. Available claims: {list(token.claims.keys())}

What it means

The Claim dependency found a valid access token, but token.claims.get(claim_name) returned None, so it raises this RuntimeError listing the claims that ARE present. FastMCP distinguishes this from the no-token case so you can tell an auth setup problem from a claim-name/schema mismatch. Note it also fires when the claim exists but its value is None or falsy-None, since only None triggers the branch.

Source

Thrown at fastmcp_slim/fastmcp/server/dependencies.py:1346

# --- Token Claim dependency ---


class _TokenClaim(Dependency[str]):
    """Dependency that extracts a specific claim from the access token."""

    def __init__(self, claim_name: str):
        self.claim_name = claim_name

    async def __aenter__(self) -> str:
        token = get_access_token()
        if token is None:
            raise RuntimeError(
                f"No access token available. Cannot extract claim '{self.claim_name}'."
            )
        value = token.claims.get(self.claim_name)
        if value is None:
            raise RuntimeError(
                f"Claim '{self.claim_name}' not found in access token. "
                f"Available claims: {list(token.claims.keys())}"
            )
        return str(value)

    async def __aexit__(
        self,
        exc_type: type[BaseException] | None,
        exc_value: BaseException | None,
        traceback: TracebackType | None,
    ) -> None:
        pass


def TokenClaim(name: str) -> str:
    """Get a specific claim from the access token.

    This dependency extracts a single claim value from the current access token.

View on GitHub (pinned to 1f02114297)

Solutions

  1. Inspect the Available claims list in the message and correct the claim name in your Claim(...) call
  2. Decode the actual token (jwt.io or logs) to see the real claim keys your auth provider emits
  3. Configure the auth provider to include the needed claim in the access token (mappers/scope mappings)
  4. If the claim is optional, use get_access_token() and token.claims.get(name, default) instead

Example fix

// before
async def role() -> str:
    with Claim("role") as r:  # token only has 'roles'
        return r
// after
async def role() -> str:
    with Claim("roles") as r:
        return r
Defensive patterns

Strategy: fallback

Validate before calling

from fastmcp.server.dependencies import get_access_token
token = get_access_token()
value = token.claims.get('sub') if token else None
if value is None:
    ...  # fallback or error before raising

Type guard

from fastmcp.server.dependencies import get_access_token

def get_claim(name: str) -> str | None:
    token = get_access_token()
    v = token.claims.get(name) if token else None
    return str(v) if v is not None else None

Try / catch

try:
    async with Claim('roles') as roles:
        return roles.split()
except RuntimeError as e:
    if 'not found in access token' in str(e):
        logger.warning('claims available: check message for actual keys')
        return []

Prevention

When it happens

Trigger: Entering `with Claim("roles")` when the token's claims dict has no "roles" key; the auth provider issues tokens with different claim names (e.g. "scope" vs "scopes", OIDC "preferred_username" vs custom "username"); the claim value is literally null in the JWT payload.

Common situations: Switching identity providers (Auth0 → Keycloak) with different claim vocabularies; forgetting that ID token claims vs access token claims differ; typos in claim names; token templates/mappings not configured on the auth server.

Related errors


AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29). Data as JSON: /api/errors/0b8770dda1626ff3. Report an issue: GitHub.