PrefectHQ/fastmcp · error · ValueError
Unsupported algorithm {algorithm!r} for issuer {issuer!r}: m
Error message
Unsupported algorithm {algorithm!r} for issuer {issuer!r}: must be one of {supported} What it means
The per-issuer `algorithms` mapping lets you pin an algorithm per trusted issuer; each value must be one of the asymmetric algorithms JWTVerifier supports. The validator rejects the whole mapping if any issuer's algorithm is unsupported, surfacing config mistakes at load time.
Source
Thrown at fastmcp_slim/fastmcp/server/auth/identity_assertion.py:176
# 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
class IdentityAssertionError(Exception):
"""Raised when an ID-JAG fails validation.
The message is for server-side logging only; the token endpoint maps this to a
generic OAuth error response and does not leak the detail to the client.
"""
class IdentityAssertionValidator:
"""Validates ID-JAG assertions for the SEP-990 jwt-bearer grant.
Reuses :class:`JWTVerifier` for signature, issuer, audience, and expiry checksView on GitHub (pinned to 1f02114297)
Solutions
- Replace the offending issuer's algorithm with a supported one (e.g. "RS256", "ES256")
- Drop the per-issuer entry for that issuer so it uses the default algorithm selection
- Fix casing/typos so the algorithm name exactly matches a member of SUPPORTED_ASSERTION_ALGORITHMS
Example fix
# before
IdentityAssertionSettings(algorithms={"https://issuer.example": "HS256"})
# after
IdentityAssertionSettings(algorithms={"https://issuer.example": "RS256"}) Defensive patterns
Strategy: validation
Validate before calling
for issuer, alg in (per_issuer_algorithms or {}).items():
if alg not in SUPPORTED_ASSERTION_ALGORITHMS:
raise ValueError(f"issuer {issuer!r}: unsupported algorithm {alg!r}") Type guard
def all_algorithms_supported(m: dict[str, str] | None) -> bool:
return m is None or all(a in SUPPORTED_ASSERTION_ALGORITHMS for a in m.values()) Try / catch
try:
settings = IdentityAssertionSettings(algorithms=algorithms)
except ValidationError as e:
logger.error("Per-issuer algorithm invalid: %s", e)
raise SystemExit(1) Prevention
- Check every per-issuer value against SUPPORTED_ASSERTION_ALGORITHMS when building the mapping
- Fix typos and casing — algorithm names are case-sensitive
- Migrate HS* entries to asymmetric algorithms when moving to JWKS verification
- Validate the whole mapping at startup rather than per-request
When it happens
Trigger: Passing `algorithms={"https://issuer.example": "HS256"}` or a typo like `"rs526"`/`"EdDSA"` in the per-issuer mapping — `_validate_algorithms` runs during settings model validation.
Common situations: Same as the global algorithm error but scoped to a specific issuer: copied a shared-secret config per issuer, case/typo mistakes in algorithm names, mixed config from multiple providers where one issuer's entry is stale.
Related errors
- Unsupported algorithm {v!r} for identity assertion: trusted
- Invalid URL: {url}
- At least one of 'tools', 'include_tags', or 'exclude_tags' i
- No MCP servers defined in the config: {file_path}
- CIMD document must have jwks_uri or jwks for private_key_jwt
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/2b1148f1663e04f0.
Report an issue: GitHub.