{"record":{"id":"a280f660687d6773","repo":"quarkusio/quarkus","slug":"a-receiver-method-must-have-exactly-one-parameter","errorCode":null,"errorMessage":"A receiver method must have exactly one parameter annotated with @Receives: ${methodDesc}","messagePattern":"A receiver method must have exactly one parameter annotated with @Receives: (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/signals/deployment/src/main/java/io/quarkus/signals/deployment/SignalsProcessor.java","lineNumber":135,"sourceCode":"            ClassInfo beanClass = bean.getTarget().get().asClass();\n            if (!hasReceiverInHierarchy(beanClass, classesWithReceivers, index)) {\n                continue;\n            }\n            // Walk the class hierarchy; methods seen in subclasses override those from superclasses\n            Set<MethodSignatureKey> seenMethods = new HashSet<>();\n            ClassInfo current = beanClass;\n            while (current != null) {\n                for (MethodInfo method : current.methods()) {\n                    if (method.isSynthetic() || method.isConstructor()) {\n                        continue;\n                    }\n                    List<MethodParameterInfo> params = method.parameters();\n                    MethodParameterInfo signalParam = null;\n                    if (!params.isEmpty()) {\n                        for (MethodParameterInfo param : params) {\n                            if (param.hasDeclaredAnnotation(DotNames.RECEIVES)) {\n                                if (signalParam != null) {\n                                    throw new IllegalStateException(\n                                            \"A receiver method must have exactly one parameter annotated with @Receives: \"\n                                                    + methodDesc(method));\n                                }\n                                signalParam = param;\n                            }\n                        }\n                    }\n                    if (!seenMethods.add(method.signatureKey())) {\n                        // Overridden by a subclass\n                        continue;\n                    }\n                    if (signalParam != null) {\n                        if (Modifier.isPrivate(method.flags())) {\n                            throw new IllegalStateException(\n                                    \"A receiver method must not be private: \" + methodDesc(method));\n                        }\n                        if (Modifier.isStatic(method.flags())) {\n                            throw new IllegalStateException(","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/signals/deployment/src/main/java/io/quarkus/signals/deployment/SignalsProcessor.java#L117-L153","documentation":"At Quarkus build time, the signals extension scans bean classes for signal receiver methods - methods with exactly one parameter annotated @Receives (e.g. @Receives SIGINT). If such a method has two or more parameters annotated @Receives, build fails with this IllegalStateException naming the method.","triggerScenarios":"Declaring a method like void handle(@Receives Signal a, @Receives Signal b) in a CDI bean; the SignalsProcessor.collectReceivers build step detects the second @Receives-annotated parameter during deployment.","commonSituations":"Developers expecting a receiver method to observe multiple signals simultaneously and annotating several parameters; copy-paste of a receiver signature then adding another @Receives param; misunderstanding that one method handles one signal.","solutions":["Keep exactly one @Receives-annotated parameter per method; declare a separate method for each signal","Move additional signal handling into other bean methods, each with a single @Receives parameter","Non-signal parameters are allowed but must be resolvable beans (they use argument lookup) - only one may carry @Receives"],"exampleFix":"// before\nvoid onSignal(@Receives Signal sigint, @Receives Signal sigterm) {...}\n// after\nvoid onSigint(@Receives Signal sigint) {...}\nvoid onSigterm(@Receives Signal sigterm) {...}","handlingStrategy":"validation","validationCode":"// Audit receiver methods before build: each must have exactly one @Receives parameter\n// grep -rn \"@Receives\" src/main/java | check enclosing signatures","typeGuard":null,"tryCatchPattern":null,"preventionTips":["One @Receives parameter per method - one method per signal","Review signatures when copy-pasting receiver methods","Remember additional (non-@Receives) parameters must be injectable beans","Run the build early; this fails at deployment, not runtime"],"tags":["quarkus","build-time","signals","cdi"],"backgroundTag":"invalid-annotated-method-signature","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}