quarkusio/quarkus · error · IllegalStateException
Current principal ${principal} is not a JSON web token
Error message
Current principal ${principal} is not a JSON web token What it means
The JwtPrincipalProducer resolves the current security identity and returns its principal as a JsonWebToken; anonymous identities get a NullJsonWebToken sentinel. If the identity is authenticated but its principal is not a JsonWebToken (i.e. the request was authenticated by a mechanism other than SmallRye JWT), the producer throws this IllegalStateException when JsonWebToken is produced into the application.
Source
Thrown at extensions/smallrye-jwt/runtime/src/main/java/io/quarkus/smallrye/jwt/runtime/auth/JwtPrincipalProducer.java:36
@Inject
SecurityIdentity identity;
/**
* The producer method for the current JsonWebToken
*
* @return JsonWebToken
*/
@Produces
@RequestScoped
JsonWebToken currentJWTPrincipalOrNull() {
if (identity.isAnonymous()) {
return new NullJsonWebToken();
}
if (identity.getPrincipal() instanceof JsonWebToken) {
return (JsonWebToken) identity.getPrincipal();
}
throw new IllegalStateException("Current principal " + identity.getPrincipal() + " is not a JSON web token");
}
}
View on GitHub (pinned to e1c734241f)
Solutions
- Ensure the request is actually authenticated via quarkus-smallrye-jwt (mp.jwt.verify.* / quarkus.smallrye-jwt config) so the principal is a JsonWebToken
- If OIDC is the real mechanism, consume the OIDC identity instead of JsonWebToken
- Guard the injection point: inject SecurityIdentity and check getPrincipal() instanceof JsonWebToken before use
- Fix test security setup to provide a JWT principal when testing JWT paths
Example fix
// before
@Inject JsonWebToken jwt; // fails for non-JWT auth mechanisms
// after
@Inject SecurityIdentity identity;
String upn() {
if (identity.getPrincipal() instanceof JsonWebToken jwt) {
return jwt.getSubject();
}
return identity.getPrincipal().getName();
} Defensive patterns
Strategy: type-guard
Validate before calling
@Inject SecurityIdentity identity;
JsonWebToken jwtOrNull() {
return identity.getPrincipal() instanceof JsonWebToken jwt ? jwt : null;
} Type guard
static boolean isJwtPrincipal(SecurityIdentity identity) {
return !identity.isAnonymous() && identity.getPrincipal() instanceof JsonWebToken;
} Try / catch
try {
JsonWebToken jwt = jwtPrincipalProducer.currentJWTPrincipalOrNull();
} catch (IllegalStateException e) {
if (e.getMessage().contains("is not a JSON web token")) {
log.warn("Request not authenticated via JWT; falling back to generic principal");
return identity.getPrincipal().getName();
}
throw e;
} Prevention
- Inject SecurityIdentity and narrow with instanceof instead of injecting JsonWebToken directly in mixed-auth apps
- Keep smallrye-jwt auth the sole mechanism for endpoints that inject JsonWebToken
- Align TestSecurity setups with the production auth mechanism
- Document per-endpoint auth mechanisms next to JWT injection points
When it happens
Trigger: Injecting JsonWebToken (or calling this producer) in a request authenticated by Basic auth, form auth, OIDC bearer token authentication, or any non-smallrye-jwt mechanism — identity.getPrincipal() is then not a JWT.
Common situations: Mixed authentication setups where some endpoints use quarkus-oidc bearer auth and code also injects JsonWebToken; Basic-auth protected management endpoints with JWT-injecting beans; testing with TestSecurity using a non-JWT principal; JWT auth disabled by misconfiguration while code assumes it.
Related errors
- No IdentityProviders were registered to handle Authenticatio
- No AnonymousIdentityProvider registered. An instance of Anon
- No producers for required item %s, step builder used: %s
- cycle detection failure report (dynamic CycleBuildException
- No datasource named '<dataSourceName>' exists
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/430647ee6e5b7f0c.
Report an issue: GitHub.