dotnet/aspnetcore · error · RuntimeException

Invocation provides %d argument(s) but target expects %d.

Error message

Invocation provides %d argument(s) but target expects %d.

What it means

bindArguments compares the number of arguments in the incoming InvocationMessage against the number of parameter types the InvocationBinder returns for the target hub method. They must be equal; otherwise the invocation cannot be bound and a RuntimeException is thrown.

Source

Thrown at src/SignalR/clients/java/signalr/messagepack/src/main/java/com/microsoft/signalr/messagepack/MessagePackHubProtocol.java:515

        return streams;
    }

    private void writeStreamIds(Collection<String> streamIds, MessagePacker packer) throws IOException {
        if (streamIds != null) {
            packer.packArrayHeader(streamIds.size());
            for (String s: streamIds) {
                packer.packString(s);
            }
        } else {
            packer.packArrayHeader(0);
        }
    }

    private Object[] bindArguments(MessageUnpacker unpacker, List<Type> paramTypes, ByteBuffer payload) throws IOException {
        int argumentCount = unpacker.unpackArrayHeader();

        if (paramTypes.size() != argumentCount) {
            throw new RuntimeException(String.format("Invocation provides %d argument(s) but target expects %d.", argumentCount, paramTypes.size()));
        }

        Object[] arguments = new Object[argumentCount];

        for (int i = 0; i < argumentCount; i++) {
            arguments[i] = readValue(unpacker, paramTypes.get(i), payload, true);
        }

        return arguments;
    }

    private Object readValue(MessageUnpacker unpacker, Type itemType, ByteBuffer payload, boolean outermostCall) throws IOException {
        Class<?> itemClass = Utils.typeToClass(itemType);
        MessageFormat messageFormat = unpacker.getNextFormat();
        ValueType valueType = messageFormat.getValueType();
        int length;
        long readBytesStart;
        Object item = null;

View on GitHub (pinned to 294cab2f9b)

Solutions

  1. Align the number of arguments sent with the hub method's parameter count.
  2. For .on(...) client methods, register a callback whose arity matches what the server sends.
  3. Rebuild and redeploy both sides after any hub signature change.

Example fix

// before
// server: public void Add(int a) {}
hubConnection.send("Add", 1, 2);

// after
hubConnection.send("Add", 1);
Defensive patterns

Strategy: validation

Validate before calling

// Java - confirm arity before invoking
java.lang.reflect.Method m = hubMethods.get(target);
if (m != null && m.getParameterCount() != args.length) {
    throw new IllegalArgumentException("Argument count mismatch for " + target);}

Try / catch

// Java
hubConnection.on("Method", (a, b) -> {}, String.class, String.class);
try {
    hubConnection.send("Method", "one").blockingAwait();
} catch (RuntimeException ex) {
    if (ex.getMessage() != null && ex.getMessage().contains("argument(s) but target expects")) {
    }
}

Prevention

When it happens

Trigger: Client invokes a server hub method with N args but the method is defined with M; server invokes a client method registered via .on(...) with a different arg count; a hub method signature was changed on one side only.

Common situations: Hub method signature refactored without updating clients; client-side .on(...) handler registered with the wrong parameter list; version skew between deployed server and client.

Related errors


AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06). Data as JSON: /api/errors/67423b486c1cd978. Report an issue: GitHub.