dotnet/aspnetcore · error · RuntimeException
There are no callbacks registered for the method
Error message
There are no callbacks registered for the method '%s'.
What it means
Inside the HubConnection binder, getParameterTypes(methodName) is called by the protocol layer to deserialize an inbound server->client InvocationMessage. If handlers were registered for the method name but the list is empty (a registration bug), the binder cannot determine parameter types and throws. A null handler list is handled separately (returns emptyArray with a warning); only a non-null but empty list triggers this throw.
Solutions
- Ensure hub.on(method, action) actually adds a non-null action; verify with hub.off() then re-on() if the list may be stale.
- After unregistering handlers, call hub.off(method) to fully remove the entry rather than leaving an empty list.
- Upgrade the client - this is a defensive throw for an internal invariant; if hit with correct on() usage, file an issue.
Example fix
// before
hub.on("Update", null); // produces empty handler list
// after
hub.on("Update", msg -> { /* handle */ });
// to remove:
hub.remove("Update"); Defensive patterns
Strategy: validation
Validate before calling
// Before relying on a handler, ensure it is actually registered.
// (No public getter exists; track registrations yourself.)
Set<String> registeredMethods = ConcurrentHashMap.newKeySet();
hub.on("Update", msg -> { registeredMethods.add("Update"); /*handle*/ registeredMethods.add("Update"); });
// Server will only invoke methods present in this set with a non-empty handler. Try / catch
// The throw surfaces during message binding. If hit, the inbound message is dropped.
// Log it and verify your on() registrations.
hub.onClosed(ex -> {
if (ex != null && ex.getMessage().contains("no callbacks registered")) {
log.error("Handler missing for server-invoked method; re-register and reconnect");
}
}); Prevention
- Always pass a non-null action to hub.on(method, action).
- Use hub.remove(method) (not partial removal) to clear handlers cleanly.
- Add an integration test that has the server invoke each registered client method.
When it happens
Trigger: Server invokes a client method for which hub.on(method, ...) was called with an action that got removed/never set, leaving an empty List<InvocationHandler> in the handlers map. The binder then cannot read argument types for deserialization.
Common situations: A handler was registered then unregistered but the empty list entry was not removed from the map; misuse of the on() API leaving a placeholder; reflection-based handler registration that produced zero handlers.
Related errors
- Cannot handle type class
- Connection is not active.
- Invocation provides argument(s) but target expects .
- 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/1ee93f27a3686dda.
Report an issue: GitHub.
Appendix: source
Thrown at src/SignalR/clients/java/signalr/core/src/main/java/com/microsoft/signalr/HubConnection.java:1647
public Type getReturnType(String invocationId) {
InvocationRequest irq = getInvocation(invocationId);
if (irq == null) {
return null;
}
return irq.getReturnType();
}
@Override
public List<Type> getParameterTypes(String methodName) {
List<InvocationHandler> handlers = connection.handlers.get(methodName);
if (handlers == null) {
logger.warn("Failed to find handler for '{}' method.", methodName);
return emptyArray;
}
if (handlers.isEmpty()) {
throw new RuntimeException(String.format("There are no callbacks registered for the method '%s'.", methodName));
}
return handlers.get(0).getTypes();
}
private void errorHandshake(Exception error) {
lock.lock();
try {
// If onError is called on a completed subject the global error handler is called
if (!(handshakeResponseSubject.hasComplete() || handshakeResponseSubject.hasThrowable())) {
handshakeResponseSubject.onError(error);
}
} finally {
lock.unlock();
}
}
}
View on GitHub (pinned to 3600ca084e)