dotnet/aspnetcore · error · RuntimeException

The 'invoke' method cannot be called if the connection is…

Error message

The 'invoke' method cannot be called if the connection is not active.

What it means

The Completable-returning invoke(method, args) overload checks that the connection is in the CONNECTED state before allocating an invocation id and dispatching. Any other state (CONNECTING, RECONNECTING, DISCONNECTED) causes an immediate RuntimeException under the state lock.

Solutions

  1. Chain the invoke after start() completes: hub.start().andThen(hub.invoke("M")).subscribe(...).
  2. Reconnect on close: register onClosed(...) to call start() again, then retry the invoke.
  3. Track connection state in your own flag updated from onClosed/onReconnected and skip or queue invocations when not connected.

Example fix

// before
hub.start();
hub.invoke("Method").await();

// after
hub.start().blockingAwait();
hub.invoke("Method").await();
Defensive patterns

Strategy: validation

Validate before calling

if (hub.getConnectionState() != HubConnectionState.CONNECTED) {
  // do not call invoke; reconnect first
  return;
}

Try / catch

try {
  hub.invoke(method, args).await();
} catch (RuntimeException e) {
  if (e.getMessage().contains("connection is not active")) {
    // schedule retry after reconnect
  } else throw e;
}

Prevention

When it happens

Trigger: Calling the Completable invoke() before start() finished, after stop(), or while the connection is mid-reconnect. The check happens inside this.state.lock()/unlock() so the read is consistent but the call still fails if the state is not CONNECTED.

Common situations: Invoking from a background thread that does not synchronize with the connection lifecycle; an onClosed handler that did not restart the connection before the next invoke; invoking from application shutdown after stop() was already called.

Related errors


AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11). Data as JSON: /api/errors/931fb9a56051b891. Report an issue: GitHub.

Appendix: source

Thrown at src/SignalR/clients/java/signalr/core/src/main/java/com/microsoft/signalr/HubConnection.java:675

                streams.add(stream);
            }
        }

        return params.toArray();
    }

    /**
     * Invokes a hub method on the server using the specified method name and arguments.
     *
     * @param method The name of the server method to invoke.
     * @param args The arguments used to invoke the server method.
     * @return A Completable that indicates when the invocation has completed.
     */
    public Completable invoke(String method, Object... args) {
        this.state.lock();
        try {
            if (this.state.getHubConnectionState() != HubConnectionState.CONNECTED) {
                throw new RuntimeException("The 'invoke' method cannot be called if the connection is not active.");
            }

            ConnectionState connectionState = this.state.getConnectionStateUnsynchronized(false);
            String id = connectionState.getNextInvocationId();

            CompletableSubject subject = CompletableSubject.create();
            InvocationRequest irq = new InvocationRequest(null, id);
            connectionState.addInvocation(irq);

            Subject<Object> pendingCall = irq.getPendingCall();

            pendingCall.subscribe(result -> subject.onComplete(),
                    error -> subject.onError(error),
                    () -> subject.onComplete());

            // Make sure the actual send is after setting up the callbacks otherwise there is a race
            // where the map doesn't have the callbacks yet when the response is returned
            sendInvocationMessage(method, args, id, false);

View on GitHub (pinned to 3600ca084e)