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

  1. Make the bean @RequestScoped
  2. Wrap the field type with org.eclipse.microprofile.jwt.ClaimValue<T>
  3. 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

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


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/a3a3648ebb276193. Report an issue: GitHub.