{"record":{"id":"2b1148f1663e04f0","repo":"PrefectHQ/fastmcp","slug":"unsupported-algorithm-algorithm-r-for-issuer-is","errorCode":null,"errorMessage":"Unsupported algorithm {algorithm!r} for issuer {issuer!r}: must be one of {supported}","messagePattern":"Unsupported algorithm (.+?) for issuer (.+?): must be one of (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/server/auth/identity_assertion.py","lineNumber":176,"sourceCode":"        # anything else (EdDSA, or a typo like RS999) would otherwise surface\n        # as a 500 on the first exchange instead of a clean config error now.\n        if v is not None and v not in SUPPORTED_ASSERTION_ALGORITHMS:\n            supported = \", \".join(sorted(SUPPORTED_ASSERTION_ALGORITHMS))\n            raise ValueError(\n                f\"Unsupported algorithm {v!r} for identity assertion: trusted \"\n                f\"issuers are verified via JWKS, so algorithm must be one of \"\n                f\"{supported}\"\n            )\n        return v\n\n    @field_validator(\"algorithms\")\n    @classmethod\n    def _validate_algorithms(cls, v: dict[str, str] | None) -> dict[str, str] | None:\n        if v is not None:\n            for issuer, algorithm in v.items():\n                if algorithm not in SUPPORTED_ASSERTION_ALGORITHMS:\n                    supported = \", \".join(sorted(SUPPORTED_ASSERTION_ALGORITHMS))\n                    raise ValueError(\n                        f\"Unsupported algorithm {algorithm!r} for issuer \"\n                        f\"{issuer!r}: must be one of {supported}\"\n                    )\n        return v\n\n\nclass IdentityAssertionError(Exception):\n    \"\"\"Raised when an ID-JAG fails validation.\n\n    The message is for server-side logging only; the token endpoint maps this to a\n    generic OAuth error response and does not leak the detail to the client.\n    \"\"\"\n\n\nclass IdentityAssertionValidator:\n    \"\"\"Validates ID-JAG assertions for the SEP-990 jwt-bearer grant.\n\n    Reuses :class:`JWTVerifier` for signature, issuer, audience, and expiry checks","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/server/auth/identity_assertion.py#L158-L194","documentation":"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.","triggerScenarios":"Passing `algorithms={\"https://issuer.example\": \"HS256\"}` or a typo like `\"rs526\"`/`\"EdDSA\"` in the per-issuer mapping — `_validate_algorithms` runs during settings model validation.","commonSituations":"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.","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"],"exampleFix":"# before\nIdentityAssertionSettings(algorithms={\"https://issuer.example\": \"HS256\"})\n# after\nIdentityAssertionSettings(algorithms={\"https://issuer.example\": \"RS256\"})","handlingStrategy":"validation","validationCode":"for issuer, alg in (per_issuer_algorithms or {}).items():\n    if alg not in SUPPORTED_ASSERTION_ALGORITHMS:\n        raise ValueError(f\"issuer {issuer!r}: unsupported algorithm {alg!r}\")","typeGuard":"def all_algorithms_supported(m: dict[str, str] | None) -> bool:\n    return m is None or all(a in SUPPORTED_ASSERTION_ALGORITHMS for a in m.values())","tryCatchPattern":"try:\n    settings = IdentityAssertionSettings(algorithms=algorithms)\nexcept ValidationError as e:\n    logger.error(\"Per-issuer algorithm invalid: %s\", e)\n    raise SystemExit(1)","preventionTips":["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"],"tags":["config","jwt","algorithm","validation"],"backgroundTag":"unsupported-jwt-algorithm","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}