{"record":{"id":"7a4bd8ec5a4601fe","repo":"quarkusio/quarkus","slug":"resource-classes-that-use-field-injection-for-rest-7a4bd8","errorCode":null,"errorMessage":"Resource classes that use field injection for REST parameters can only be @RequestScoped. Offending class is ${clazz.name()}","messagePattern":"Resource classes that use field injection for REST parameters can only be @RequestScoped\\. Offending class is (.+?)","errorType":"exception","errorClass":"DeploymentException","httpStatus":null,"severity":"error","filePath":"extensions/resteasy-reactive/rest/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/ResteasyReactiveCDIProcessor.java","lineNumber":112,"sourceCode":"                .getRequestScopedResources();\n\n        additionalBeanBuildItemBuildProducer.produce(new io.quarkus.arc.deployment.AnnotationsTransformerBuildItem(\n                AnnotationTransformation.builder().whenDeclaration(\n                        new Predicate<>() {\n                            @Override\n                            public boolean test(Declaration declaration) {\n                                return declaration.kind() == AnnotationTarget.Kind.CLASS;\n                            }\n                        }).transform(new Consumer<>() {\n                            @Override\n                            public void accept(AnnotationTransformation.TransformationContext context) {\n                                if (context.declaration().kind() == AnnotationTarget.Kind.CLASS) {\n                                    ClassInfo clazz = context.declaration().asClass();\n                                    if (requestScopedResources.contains(clazz.name())) {\n                                        BuiltinScope builtinScope = BuiltinScope.from(clazz);\n                                        if (builtinScope != null) {\n                                            if (builtinScope.getName() != BuiltinScope.REQUEST.getName()) {\n                                                throw new DeploymentException(\n                                                        \"Resource classes that use field injection for REST parameters can only be @RequestScoped. Offending class is \"\n                                                                + clazz.name());\n                                            } else {\n                                                // nothing to do as @RequestScoped was already present\n                                            }\n                                        } else if (!resourceScanningResultBuildItem.get().getResult().getPossibleSubResources()\n                                                .containsKey(clazz.name())) {\n                                            // no @RequestScoped for Sub Resources, since they might have a constructor\n                                            // not compatible with CDI. User must explicitly mark as RequestScoped\n                                            context.add(RequestScoped.class);\n                                        }\n                                    }\n                                }\n                            }\n                        })));\n    }\n\n    @BuildStep","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/resteasy-reactive/rest/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/ResteasyReactiveCDIProcessor.java#L94-L130","documentation":"During CDI processing, Quarkus automatically adds @RequestScoped to resource classes that use field injection of REST parameters — unless the class already declares a different builtin scope. If a resource that needs field injection carries an explicit scope other than @RequestScoped, deployment aborts with this DeploymentException (same rule as the indexer-side check, enforced while synthesizing scopes).","triggerScenarios":"A resource class found in requestScopedResources (i.e. it uses field injection of REST parameters) has an explicit @Singleton/@ApplicationScoped/other builtin scope annotation; the synthetic-scope CDI build step detects the mismatch and fails the build.","commonSituations":"Annotating resources @ApplicationScoped while using @QueryParam fields; a parent class or stereotype pulling in a different scope; adding field injection later to an already-scoped resource.","solutions":["Change the resource scope annotation to @RequestScoped","Move REST parameter injection from fields to resource method parameters, allowing any scope","Use constructor injection instead of field injection"],"exampleFix":"// before\n@Singleton\n@Path(\"/items\")\npublic class ItemResource {\n    @PathParam(\"id\")\n    String id;\n}\n// after\n@RequestScoped\n@Path(\"/items\")\npublic class ItemResource {\n    @PathParam(\"id\")\n    String id;\n}","handlingStrategy":"validation","validationCode":"if (Arrays.stream(clazz.getDeclaredFields())\n        .anyMatch(f -> Arrays.stream(f.getAnnotations())\n                .anyMatch(a -> a.annotationType().getName().startsWith(\"jakarta.ws.rs.\")))) {\n    if (clazz.isAnnotationPresent(jakarta.inject.Singleton.class)\n            || clazz.isAnnotationPresent(jakarta.enterprise.context.ApplicationScoped.class))\n        throw new IllegalStateException(clazz + \" needs field injection: use @RequestScoped or method params\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do not combine explicit non-request scopes with REST parameter field injection","Migrate field injection to method parameter injection when a broader scope is required","Check parent classes/stereotypes that might contribute a conflicting scope"],"tags":["cdi","scope","jax-rs","resteasy-reactive","field-injection"],"backgroundTag":"field-injection-scope-violation","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"}