{"record":{"id":"f7428048f6d2a603","repo":"quarkusio/quarkus","slug":"actualtype-type-can-not-be-used-to-represent-jw","errorCode":null,"errorMessage":"${actualType} 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","messagePattern":"(.+?) 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","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/smallrye-jwt/deployment/src/main/java/io/quarkus/smallrye/jwt/deployment/SmallRyeJwtProcessor.java","lineNumber":204,"sourceCode":"            if (injectionPoint.hasDefaultedQualifier()) {\n                continue;\n            }\n            AnnotationInstance claimQualifier = injectionPoint.getRequiredQualifier(CLAIM_NAME);\n            if (claimQualifier != null) {\n                Type actualType = injectionPoint.getRequiredType();\n\n                Optional<BeanInfo> bean = injectionPoint.getTargetBean();\n                if (bean.isPresent()) {\n                    DotName scope = bean.get().getScope().getDotName();\n                    if (!REQUEST_SCOPED_NAME.equals(scope)\n                            && (!ALL_PROVIDER_NAMES.contains(injectionPoint.getType().name())\n                                    && !CLAIM_VALUE_NAME.equals(actualType.name()))) {\n                        String error = String.format(\n                                \"%s type can not be used to represent JWT claims in @Singleton or @ApplicationScoped beans\"\n                                        + \", make the bean @RequestScoped or wrap this type with org.eclipse.microprofile.jwt.ClaimValue\"\n                                        + \" or jakarta.inject.Provider or jakarta.enterprise.inject.Instance\",\n                                actualType.name());\n                        throw new IllegalStateException(error);\n                    }\n                }\n\n                if (injectionPoint.getType().name().equals(DotNames.PROVIDER) && actualType.name().equals(DotNames.OPTIONAL)) {\n                    additionalTypes.add(actualType);\n                }\n            }\n\n        }\n\n        // Register a custom bean\n        BeanConfigurator<Optional<?>> configurator = beanRegistrationPhase.getContext().configure(Optional.class);\n        for (Type type : additionalTypes) {\n            configurator.addType(type);\n        }\n        configurator.scope(BuiltinScope.DEPENDENT.getInfo());\n        configurator.qualifiers(AnnotationInstance.create(CLAIM_NAME, null,\n                new AnnotationValue[] { AnnotationValue.createStringValue(\"value\", \"\"),","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/smallrye-jwt/deployment/src/main/java/io/quarkus/smallrye/jwt/deployment/SmallRyeJwtProcessor.java#L186-L222","documentation":"When a JWT claim is injected (e.g. Optional<X> or raw X via @Claim) into a @Singleton or @ApplicationScoped bean, the value would be resolved once at bean creation outside any request, so it cannot represent a per-request claim. The extension's build step inspects such injection points and throws this IllegalStateException at build time, telling you to make the bean request-scoped or wrap the type in ClaimValue/Provider/Instance for lazy per-request resolution.","triggerScenarios":"@Inject @Claim(claim = \"...\") Optional<String> claim (or a similar non-ClaimValue type) inside a bean annotated @Singleton or @ApplicationScoped; including cases where actualType is Optional (or non-ClaimValue) in such beans.","commonSituations":"Injecting claims into application-wide services (config holders, scheduled jobs); refactoring a @RequestScoped bean to @Singleton (or @ApplicationScoped) and forgetting the claim injection; copying claim-injection snippets into singleton REST resources.","solutions":["Make the bean @RequestScoped so the claim resolves per request","Wrap the injected type with org.eclipse.microprofile.jwt.ClaimValue (e.g. ClaimValue<Optional<String>>)","Wrap with jakarta.inject.Provider<T> or jakarta.enterprise.inject.Instance<T> to defer resolution to access time"],"exampleFix":"// before\n@ApplicationScoped\npublic class ClaimService {\n    @Inject\n    @Claim(claim = \"upn\")\n    Optional<String> upn; // build-time failure\n}\n\n// after\n@ApplicationScoped\npublic class ClaimService {\n    @Inject\n    ClaimValue<Optional<String>> upn; // resolved lazily per request\n}","handlingStrategy":"type-guard","validationCode":"// Prefer ClaimValue/Provider/Instance when injecting claims into non-request-scoped beans\n@Inject ClaimValue<Optional<String>> upn; // safe in @ApplicationScoped","typeGuard":"// Guard: claims may only be injected directly in request-scoped beans\nstatic boolean isDirectClaimInjectionSafe(Class<?> beanClass) {\n    return beanClass.isAnnotationPresent(jakarta.enterprise.context.RequestScoped.class)\n            || beanClass.isAnnotationPresent(jakarta.enterprise.context.SessionScoped.class);\n}","tryCatchPattern":"try {\n    cdiContainer();\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"can not be used to represent JWT claims\")) {\n        throw new IllegalStateException(\"Use ClaimValue/Provider/Instance or make the bean @RequestScoped\", e);\n    }\n    throw e;\n}","preventionTips":["Default to ClaimValue<T> for claim injection in long-lived beans","Never convert request-scoped claim-consuming beans to @Singleton without rewiring injections","Search for @Claim fields when changing bean scopes","Review ArC build warnings about wrong-scope injections"],"tags":["jwt","cdi","build-time","quarkus"],"backgroundTag":"invalid-claim-injection-scope","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}