{"record":{"id":"4194c134f659da2f","repo":"dotnet/aspnetcore","slug":"s-already-has-a-value-returning-handler-multip","errorCode":null,"errorMessage":"'%s' already has a value returning handler. Multiple return values are not supported.","messagePattern":"'(.+?)' already has a value returning handler\\. Multiple return values are not supported\\.","errorType":"validation","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/SignalR/clients/java/signalr/core/src/main/java/com/microsoft/signalr/CallbackMap.java","lineNumber":30,"sourceCode":"\nclass CallbackMap {\n    private final Map<String, List<InvocationHandler>> handlers = new HashMap<>();\n    private final ReentrantLock lock = new ReentrantLock();\n\n    public InvocationHandler put(String target, Object action, Type... types) {\n        try {\n            lock.lock();\n            InvocationHandler handler = new InvocationHandler(action, types);\n            if (!handlers.containsKey(target)) {\n                handlers.put(target, new ArrayList<>());\n            }\n\n            List<InvocationHandler> methodHandlers;\n            methodHandlers = handlers.get(target);\n            if (handler.getHasResult()) {\n                for (InvocationHandler existingHandler : methodHandlers) {\n                    if (existingHandler.getHasResult()) {\n                        throw new RuntimeException(String.format(\"'%s' already has a value returning handler. Multiple return values are not supported.\", target));\n                    }\n                }\n            }\n            methodHandlers = new ArrayList<>(methodHandlers);\n            methodHandlers.add(handler);\n\n            // replace List in handlers map\n            handlers.remove(target);\n            handlers.put(target, methodHandlers);\n            return handler;\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    public List<InvocationHandler> get(String key) {\n        try {\n            lock.lock();","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/294cab2f9b2e03af6b953820c7ab497c3c8b7ad9/src/SignalR/clients/java/signalr/core/src/main/java/com/microsoft/signalr/CallbackMap.java#L12-L48","documentation":"CallbackMap stores handlers per hub method target. When you register an `on` handler whose action returns a value (getHasResult()==true), the map forbids a second value-returning handler for the same target, because the client can only send one result back to the server for a server-to-client invocation.","triggerScenarios":"Calling hubConnection.on(\"MethodName\", actionWithType) twice for the same MethodName where both handlers return a value; or calling on(...).on(...) after removing one but the prior returning handler still lingers.","commonSituations":"Duplicate registration during a reconnect or re-init, a refactor that registers the same handler in two places, or a handler registered both globally and in a component without cleanup.","solutions":["Keep at most one value-returning handler per method name; remove (hubConnection.remove(name, handler)) before re-registering.","Use hubConnection.on(...) once during connection setup and dispose handlers on teardown.","If multiple consumers need the same method, route through a single dispatcher that returns one value.","Audit registration paths (reconnect callbacks, DI, lifecycle hooks) for accidental double-registration."],"exampleFix":"// before\nhubConnection.on(\"Calc\", (int a) -> a + 1, int.class);\nhubConnection.on(\"Calc\", (int a) -> a * 2, int.class); // throws\n\n// after\nhubConnection.remove(\"Calc\", firstHandler);\nhubConnection.on(\"Calc\", (int a) -> a * 2, int.class);","handlingStrategy":"validation","validationCode":"Set<String> returningTargets = new HashSet<>();\nvoid register(String target, Object action, Type... types) {\n  InvocationHandler h = new InvocationHandler(action, types);\n  if (h.getHasResult() && returningTargets.contains(target)) {\n    throw new IllegalStateException(\"Returning handler already registered for \" + target);\n  }\n  if (h.getHasResult()) returningTargets.add(target);\n  // then hubConnection.on(...)\n}","typeGuard":null,"tryCatchPattern":"try {\n  hubConnection.on(\"Method\", action, types);\n} catch (RuntimeException e) {\n  if (e.getMessage().contains(\"already has a value returning handler\")) {\n    hubConnection.remove(\"Method\", previousHandler);\n    hubConnection.on(\"Method\", action, types);\n  } else throw e;\n}","preventionTips":["Register value-returning handlers once per method name at connection setup.","Always remove handlers in teardown before re-registering.","Centralize registration to avoid duplicate calls across components."],"tags":["java","signalr","handlers","validation","registration"],"analyzedSha":"294cab2f9b2e03af6b953820c7ab497c3c8b7ad9","analyzedAt":"2026-08-06T20:08:02.189Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}