PrefectHQ/fastmcp · error · ValueError
identity_assertion.trusted_issuers must not be empty
Error message
identity_assertion.trusted_issuers must not be empty
What it means
The `trusted_issuers` field on the identity_assertion settings must be a non-empty list; a pydantic `field_validator` raises this ValueError at configuration load time when the list is empty. Trusted issuers are mandatory because assertion verification is entirely driven by the issuer/JWKS list.
Source
Thrown at fastmcp_slim/fastmcp/server/auth/identity_assertion.py:146
"issuer string (mirroring `jwks_uris`). Issuers absent here fall "
"back to `algorithm`."
),
)
access_token_expiry_seconds: int = Field(
default=300,
gt=0,
description=(
"Lifetime, in seconds, of the short-lived access token minted from an "
"ID-JAG. SEP-990 relies on the client re-exchanging a fresh assertion, so "
"this is intentionally short and no refresh token is issued."
),
)
@field_validator("trusted_issuers")
@classmethod
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 "View on GitHub (pinned to 1f02114297)
Solutions
- Add at least one trusted issuer URL to the `trusted_issuers` list in your identity assertion settings
- Fix the env var / config parsing so the list is populated (check separators, quoting)
- If no issuers should be trusted, disable the identity assertion feature entirely rather than passing an empty list
Example fix
# before IdentityAssertionSettings(trusted_issuers=[]) # after IdentityAssertionSettings(trusted_issuers=["https://accounts.google.com"])
Defensive patterns
Strategy: validation
Validate before calling
issuers = [u.strip() for u in os.environ.get("TRUSTED_ISSUERS", "").split(",") if u.strip()]
if not issuers:
raise ValueError("trusted_issuers must contain at least one issuer URL") Type guard
def has_trusted_issuers(cfg: dict) -> bool:
v = cfg.get("trusted_issuers")
return isinstance(v, list) and len(v) > 0 Try / catch
try:
settings = IdentityAssertionSettings(**cfg)
except ValidationError as e:
logger.error("identity_assertion config invalid: %s", e)
raise SystemExit(1) Prevention
- Validate identity assertion config at startup with a fast-fail check
- Never build settings with a conditionally-empty trusted_issuers list
- Filter empty strings when parsing issuer lists from env vars
- Disable the feature explicitly instead of configuring an empty issuer list
When it happens
Trigger: Configuring identity assertion settings with `trusted_issuers=[]` (or constructing the settings model with an empty list) — validation fails during model instantiation, not at request time.
Common situations: Environment/config file that yields an empty list (e.g. an empty `TRUSTED_ISSUERS` env var split into `[]`); YAML/JSON config with `trusted_issuers: []`; code that builds the settings conditionally and never populates the list.
Related errors
- trusted_issuers entries must be non-empty strings
- At least one of 'tools', 'include_tags', or 'exclude_tags' i
- The API key is empty
- The Horizon API key is invalid
- Invalid URL: {url}
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/e92cee892e94005e.
Report an issue: GitHub.