{"record":{"id":"35112a5531e5b24b","repo":"quarkusio/quarkus","slug":"unable-to-inject-s-callback-parameter-s-decla-35112a","errorCode":null,"errorMessage":"Unable to inject @%s callback parameter '%s' declared on %s: ambiguous injectors found: %s","messagePattern":"Unable to inject @(.+?) callback parameter '(.+?)' declared on (.+?): ambiguous injectors found: (.+?)","errorType":"exception","errorClass":"WebSocketException","httpStatus":null,"severity":"error","filePath":"extensions/websockets-next/deployment/src/main/java/io/quarkus/websockets/next/deployment/Callback.java","lineNumber":218,"sourceCode":"        }\n        List<CallbackArgument> arguments = new ArrayList<>(parameters.size());\n        for (MethodParameterInfo parameter : parameters) {\n            List<CallbackArgument> found = callbackArguments\n                    .findMatching(parameterContext(annotation, parameter, transformedAnnotations, index));\n            if (found.isEmpty()) {\n                String msg = String.format(\"Unable to inject @%s callback parameter '%s' declared on %s: no injector found\",\n                        DotNames.simpleName(annotation.name()),\n                        parameter.name() != null ? parameter.name() : \"#\" + parameter.position(),\n                        asString());\n                throw new WebSocketException(msg);\n            } else if (found.size() > 1 && (found.get(0).priority() == found.get(1).priority())) {\n                String msg = String.format(\n                        \"Unable to inject @%s callback parameter '%s' declared on %s: ambiguous injectors found: %s\",\n                        DotNames.simpleName(annotation.name()),\n                        parameter.name() != null ? parameter.name() : \"#\" + parameter.position(),\n                        asString(),\n                        found.stream().map(p -> p.getClass().getSimpleName() + \":\" + p.priority()));\n                throw new WebSocketException(msg);\n            }\n            arguments.add(found.get(0));\n        }\n        return List.copyOf(arguments);\n    }\n\n    Type argumentType(Predicate<CallbackArgument> filter) {\n        for (int i = 0; i < arguments.size(); i++) {\n            if (filter.test(arguments.get(i))) {\n                return method.parameterType(i);\n            }\n        }\n        return null;\n    }\n\n    private ParameterContext parameterContext(AnnotationInstance callbackAnnotation, MethodParameterInfo parameter,\n            TransformedAnnotationsBuildItem transformedAnnotations, IndexView index) {\n        return new ParameterContext() {","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/websockets-next/deployment/src/main/java/io/quarkus/websockets/next/deployment/Callback.java#L200-L236","documentation":"When more than one parameter injector matches a callback parameter and the top two matches share the same priority, websockets-next cannot decide which to use and fails the build with an ambiguous-injectors WebSocketException. This prevents silently picking the wrong injector.","triggerScenarios":"A callback parameter whose annotation+type combination is matched by multiple registered ParameterConverters with equal priority — e.g. overlapping custom ParameterConverter registrations or built-in ambiguity between converters.","commonSituations":"Registering a custom ParameterConverter that also matches types already handled by built-in converters; two extensions or app classes each registering converters matching the same parameter; extension version combinations introducing overlapping converters.","solutions":["Remove or narrow your custom ParameterConverter so it does not overlap the built-in one (check its matches())","Register your converter with a higher priority than the competing one so matching is deterministic","Change the parameter annotation/type so only one converter matches","Upgrade/downgrade websockets-next if a known bug causes overlapping built-in converters"],"exampleFix":"// before: custom converter competing with built-in at same priority\n@Priority(1)\nclass MyParamConverter implements ParameterConverter { ... }\n// after\n@Priority(10)\nclass MyParamConverter implements ParameterConverter { ... }","handlingStrategy":"validation","validationCode":"// Ensure custom ParameterConverter.matches() does not overlap built-ins:\n// if (builtInMatches(param)) return false; in your converter","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Give custom converters a distinct @Priority","Narrow custom converter matches to types the framework does not handle","Avoid multiple extensions registering overlapping converters"],"tags":["quarkus","websockets-next","build-time","ambiguity"],"backgroundTag":"websocket-parameter-injector-ambiguous","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"}