{"record":{"id":"d6c739d2d729e5f8","repo":"dotnet/aspnetcore","slug":"invocation-provides-d-argument-s-but-target-expe","errorCode":null,"errorMessage":"Invocation provides %d argument(s) but target expects %d.","messagePattern":"Invocation provides (.+?) argument\\(s\\) but target expects (.+?)\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/SignalR/clients/java/signalr/core/src/main/java/com/microsoft/signalr/GsonHubProtocol.java","lineNumber":233,"sourceCode":"                    default:\n                        break;\n                }\n            }\n        } catch (IOException ex) {\n            throw new RuntimeException(\"Error reading JSON.\", ex);\n        }\n\n        return hubMessages;\n    }\n\n    @Override\n    public ByteBuffer writeMessage(HubMessage hubMessage) {\n        return ByteBuffer.wrap((gson.toJson(hubMessage) + RECORD_SEPARATOR).getBytes(StandardCharsets.UTF_8));\n    }\n\n    private ArrayList<Object> bindArguments(JsonArray argumentsToken, List<Type> paramTypes) {\n        if (argumentsToken.size() != paramTypes.size()) {\n            throw new RuntimeException(String.format(\"Invocation provides %d argument(s) but target expects %d.\", argumentsToken.size(), paramTypes.size()));\n        }\n\n        ArrayList<Object> arguments = null;\n        if (paramTypes.size() >= 1) {\n            arguments = new ArrayList<>();\n            for (int i = 0; i < paramTypes.size(); i++) {\n                arguments.add(gson.fromJson(argumentsToken.get(i), paramTypes.get(i)));\n            }\n        }\n\n        return arguments;\n    }\n\n    private ArrayList<Object> bindArguments(JsonReader reader, List<Type> paramTypes) throws IOException {\n        reader.beginArray();\n        int paramCount = paramTypes.size();\n        int argCount = 0;\n        ArrayList<Object> arguments = new ArrayList<>();","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/SignalR/clients/java/signalr/core/src/main/java/com/microsoft/signalr/GsonHubProtocol.java#L215-L251","documentation":"Thrown by GsonHubProtocol.bindArguments (the JsonArray-based path) when the number of JSON arguments in an invocation does not equal the number of parameter types the registered handler expects. The client is about to gson.fromJson each argument into its target Type and rejects a count mismatch up front to avoid silent misbinding.","triggerScenarios":"Server invokes a client method with N arguments but the Java handler registered for that target has M parameters (N != M). The handler's parameter Types come from hubConnection.on('target', (a, b) -> ..., Type1.class, Type2.class); the arguments come from the wire's 'arguments' array.","commonSituations":"Server hub method signature changed (added/removed a parameter) but the client registration was not updated; client registered with the wrong number of Type tokens; the server sends default/null arguments that still count toward the array size.","solutions":["Match the hubConnection.on(...) Type list to the server method's current parameter list - count and order.","Update the client when the server method signature changes; version-pin if you cannot deploy both at once.","Inspect the inbound invocation's arguments array length and compare to the registered Type[] length."],"exampleFix":"// before\n// C# hub: public void Send(string a, string b, int c)\n// Java: hubConnection.on(\"Send\", (a, b) -> {}, String.class, String.class); // 2 vs 3 -> throws\n\n// after\nhubConnection.on(\"Send\", (a, b, c) -> {}, String.class, String.class, Integer.class);","handlingStrategy":"validation","validationCode":"void register(HubConnection conn, String target, Type[] expected, Action<Object[]> handler) {\n  // expected[] is the documented server-side parameter list\n  conn.on(target, args -> handler.call(args), expected); // lengths are now in sync by construction\n}","typeGuard":"boolean arityMatches(Type[] registered, int wireArgCount) {\n  return registered.length == wireArgCount;\n}","tryCatchPattern":"try {\n  conn.on(\"Send\", h, String.class, Integer.class);\n} catch (RuntimeException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"argument(s) but target expects\")) {\n    // update the Type[] to match the current server method signature\n  } else throw e;\n}","preventionTips":["Mirror the server method's parameter list exactly in the on(...) Type[].","Update client registrations whenever the server method signature changes.","Version-pin client and server together when signatures are in flux."],"tags":["signalr","java","argument-binding","handler-registration","invocation"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}