dotnet/aspnetcore · error · RuntimeException
Invocation provides argument(s) but target expects .
Error message
Invocation provides %d argument(s) but target expects %d.
What it means
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.
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.
Example fix
// before
// C# hub: public void Send(string a, string b, int c)
// Java: hubConnection.on("Send", (a, b) -> {}, String.class, String.class); // 2 vs 3 -> throws
// after
hubConnection.on("Send", (a, b, c) -> {}, String.class, String.class, Integer.class); Defensive patterns
Strategy: validation
Validate before calling
void register(HubConnection conn, String target, Type[] expected, Action<Object[]> handler) {
// expected[] is the documented server-side parameter list
conn.on(target, args -> handler.call(args), expected); // lengths are now in sync by construction
} Type guard
boolean arityMatches(Type[] registered, int wireArgCount) {
return registered.length == wireArgCount;
} Try / catch
try {
conn.on("Send", h, String.class, Integer.class);
} catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().contains("argument(s) but target expects")) {
// update the Type[] to match the current server method signature
} else throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- ' ' already has a value returning handler. Multiple return…
- The 'invoke' method cannot be called if the connection is…
- The 'send' method cannot be called if the connection is not…
- A valid url is required.
- A valid url is required.
AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11).
Data as JSON: /api/errors/d6c739d2d729e5f8.
Report an issue: GitHub.
Appendix: source
Thrown at src/SignalR/clients/java/signalr/core/src/main/java/com/microsoft/signalr/GsonHubProtocol.java:233
default:
break;
}
}
} catch (IOException ex) {
throw new RuntimeException("Error reading JSON.", ex);
}
return hubMessages;
}
@Override
public ByteBuffer writeMessage(HubMessage hubMessage) {
return ByteBuffer.wrap((gson.toJson(hubMessage) + RECORD_SEPARATOR).getBytes(StandardCharsets.UTF_8));
}
private ArrayList<Object> bindArguments(JsonArray argumentsToken, List<Type> paramTypes) {
if (argumentsToken.size() != paramTypes.size()) {
throw new RuntimeException(String.format("Invocation provides %d argument(s) but target expects %d.", argumentsToken.size(), paramTypes.size()));
}
ArrayList<Object> arguments = null;
if (paramTypes.size() >= 1) {
arguments = new ArrayList<>();
for (int i = 0; i < paramTypes.size(); i++) {
arguments.add(gson.fromJson(argumentsToken.get(i), paramTypes.get(i)));
}
}
return arguments;
}
private ArrayList<Object> bindArguments(JsonReader reader, List<Type> paramTypes) throws IOException {
reader.beginArray();
int paramCount = paramTypes.size();
int argCount = 0;
ArrayList<Object> arguments = new ArrayList<>();View on GitHub (pinned to 3600ca084e)