PrefectHQ/fastmcp · error · ValueError

Unsupported algorithm {v!r} for identity assertion: trusted

Error message

Unsupported algorithm {v!r} for identity assertion: trusted issuers are verified via JWKS, so algorithm must be one of {supported}

What it means

The optional global `algorithm` for identity assertion must be one of the asymmetric JWS algorithms that JWTVerifier supports (via JWKS). HS* symmetric algorithms and unknown names are rejected at config time so they fail as a clean configuration error instead of a 500 on the first token exchange.

Source

Thrown at fastmcp_slim/fastmcp/server/auth/identity_assertion.py:162

    def _validate_trusted_issuers(cls, v: list[str]) -> list[str]:
        if not v:
            raise ValueError("identity_assertion.trusted_issuers must not be empty")
        for issuer in v:
            if not issuer or not issuer.strip():
                raise ValueError("trusted_issuers entries must be non-empty strings")
        return v

    @field_validator("algorithm")
    @classmethod
    def _validate_algorithm(cls, v: str | None) -> str | None:
        # Trusted issuers are verified via JWKS (public keys only), so the
        # algorithm must be one of the asymmetric JWS algorithms JWTVerifier
        # actually supports — HS* (shared-secret) has no JWKS equivalent, and
        # anything else (EdDSA, or a typo like RS999) would otherwise surface
        # as a 500 on the first exchange instead of a clean config error now.
        if v is not None and v not in SUPPORTED_ASSERTION_ALGORITHMS:
            supported = ", ".join(sorted(SUPPORTED_ASSERTION_ALGORITHMS))
            raise ValueError(
                f"Unsupported algorithm {v!r} for identity assertion: trusted "
                f"issuers are verified via JWKS, so algorithm must be one of "
                f"{supported}"
            )
        return v

    @field_validator("algorithms")
    @classmethod
    def _validate_algorithms(cls, v: dict[str, str] | None) -> dict[str, str] | None:
        if v is not None:
            for issuer, algorithm in v.items():
                if algorithm not in SUPPORTED_ASSERTION_ALGORITHMS:
                    supported = ", ".join(sorted(SUPPORTED_ASSERTION_ALGORITHMS))
                    raise ValueError(
                        f"Unsupported algorithm {algorithm!r} for issuer "
                        f"{issuer!r}: must be one of {supported}"
                    )
        return v

View on GitHub (pinned to 1f02114297)

Solutions

  1. Set `algorithm` to a supported asymmetric algorithm (e.g. "RS256", "ES256") — see the sorted list in the error message
  2. Remove the `algorithm` setting to use the default behavior (algorithms derived per issuer)
  3. If you need HS*, that algorithm is not supported for JWKS-verified trusted issuers — switch the issuer to asymmetric keys

Example fix

# before
IdentityAssertionSettings(trusted_issuers=[...], algorithm="HS256")
# after
IdentityAssertionSettings(trusted_issuers=[...], algorithm="RS256")
Defensive patterns

Strategy: validation

Validate before calling

SUPPORTED = {"RS256", "RS384", "RS512", "ES256", "ES384", "ES512", "PS256", "PS384", "PS512"}
if algorithm is not None and algorithm not in SUPPORTED:
    raise ValueError(f"algorithm {algorithm!r} unsupported for JWKS verification")

Type guard

def is_supported_algorithm(alg: str | None) -> bool:
    return alg is None or alg in SUPPORTED_ASSERTION_ALGORITHMS

Try / catch

try:
    settings = IdentityAssertionSettings(algorithm=alg)
except ValidationError as e:
    logger.error("Invalid identity assertion algorithm %r: %s", alg, e)
    raise SystemExit(1)

Prevention

When it happens

Trigger: Setting `algorithm="HS256"` (shared-secret — no JWKS equivalent), `algorithm="EdDSA"` (unsupported here), or a typo like `algorithm="RS999"` triggers `_validate_algorithm` during model validation.

Common situations: Copy-pasting a symmetric algorithm from a client-secret JWT setup; typos in algorithm names; migrating config from a shared-secret verifier to JWKS-based trusted-issuer verification without changing the algorithm.

Related errors


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