quarkusio/quarkus · error · IllegalStateException
%s type can not be used to represent JWT claims in @Singleto
Error message
%s type can not be used to represent JWT claims in @Singleton or @ApplicationScoped beans, make the bean @RequestScoped or wrap this type with org.eclipse.microprofile.jwt.ClaimValue or jakarta.inject.Provider or jakarta.enterprise.inject.Instance
What it means
During OIDC build-time processing, checkClaim() verifies that JWT claim injection types (@Claim JwtClaims/JsonValue-like types) are only used in beans whose scope allows per-request values. Injecting such a raw claim type into a @Singleton or @ApplicationScoped bean is rejected with IllegalStateException because the value would be computed once and shared across requests.
Source
Thrown at extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/OidcBuildStep.java:186
if (injectionPoint.hasDefaultedQualifier()) {
continue;
}
AnnotationInstance claimQualifier = injectionPoint.getRequiredQualifier(CLAIM_NAME);
if (claimQualifier != null) {
Type actualType = injectionPoint.getRequiredType();
Optional<BeanInfo> bean = injectionPoint.getTargetBean();
if (bean.isPresent()) {
DotName scope = bean.get().getScope().getDotName();
if (!REQUEST_SCOPED_NAME.equals(scope)
&& (!ALL_PROVIDER_NAMES.contains(injectionPoint.getType().name())
&& !CLAIM_VALUE_NAME.equals(actualType.name()))) {
String error = String.format(
"%s type can not be used to represent JWT claims in @Singleton or @ApplicationScoped beans"
+ ", make the bean @RequestScoped or wrap this type with org.eclipse.microprofile.jwt.ClaimValue"
+ " or jakarta.inject.Provider or jakarta.enterprise.inject.Instance",
actualType.name());
throw new IllegalStateException(error);
}
}
}
}
}
@BuildStep
AdditionalBeanBuildItem jwtClaimIntegration(Capabilities capabilities) {
if (!capabilities.isPresent(Capability.JWT)) {
AdditionalBeanBuildItem.Builder removable = AdditionalBeanBuildItem.builder();
removable.addBeanClass(CommonJwtProducer.class);
removable.addBeanClass(RawClaimTypeProducer.class);
removable.addBeanClass(JsonValueProducer.class);
removable.addBeanClass(ClaimValueProducer.class);
removable.addBeanClass(Claim.class);
return removable.build();
}View on GitHub (pinned to e1c734241f)
Solutions
- Make the bean @RequestScoped
- Wrap the field type with org.eclipse.microprofile.jwt.ClaimValue<T>
- Or inject jakarta.inject.Provider<T> / jakarta.enterprise.inject.Instance<T> instead of the raw claim type
Example fix
// before
@ApplicationScoped
class UserBean {
@Claim("sub") JsonValue subject;
}
// after
@ApplicationScoped
class UserBean {
@Claim("sub") ClaimValue<JsonValue> subject; // or make the bean @RequestScoped
} Defensive patterns
Strategy: validation
Validate before calling
// At build/design time: never inject raw @Claim types into @Singleton/@ApplicationScoped beans. // Use ClaimValue/Provider/Instance wrappers or @RequestScoped scope for the bean.
Try / catch
try { app.start(); } catch (IllegalStateException e) { if (e.getMessage().contains("can not be used to represent JWT claims")) { /* fix bean scope or wrap type */ } } Prevention
- Keep claim-injecting beans @RequestScoped
- Use ClaimValue<T> or Provider<T> for singleton beans
- Run a build (mvn verify) before deploying — this fails at build time
When it happens
Trigger: Annotating a field of claim type (e.g. JsonValue/JwtClaims style claim) with @Claim in a bean scoped @Singleton or @ApplicationScoped; CDI build-step validation flags the actualType name as non-wrapper and non-ClaimValue.
Common situations: Migrating an app from request-scoped services to singletons while keeping @Claim fields; copy-pasting claim injection into a config/utility singleton bean.
Related errors
- ${actualType} type can not be used to represent JWT claims i
- The @Blocking, @NonBlocking and @RunOnVirtualThread annotati
- Unsupported injection point target: <injectionPoint>
- Failed to find any non-blocking provider for startup actions
- Synthetic bean does not provide a creation method, use Exten
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/a3a3648ebb276193.
Report an issue: GitHub.