dotnet/aspnetcore · error · RuntimeException
Trying to send and message while the connection is not activ
Error message
Trying to send and message while the connection is not active.
What it means
A RuntimeException thrown by the internal sendHubMessageWithLock helper when the HubConnection is not CONNECTED at the moment a hub message (ping, invocation, stream item, close, cancel, completion) is about to be written. This is an internal guard beneath the public send/invoke/stream APIs and also covers messages produced by the ping timer and by upload-stream forwarding. The message text contains a typo ('send and message') but the intent is the standard 'not active' guard.
Source
Thrown at src/SignalR/clients/java/signalr/core/src/main/java/com/microsoft/signalr/HubConnection.java:828
sendInvocationMessage(method, args, invocationId, true);
return observable.doOnDispose(() -> {
if (subscriptionCount.decrementAndGet() == 0) {
CancelInvocationMessage cancelInvocationMessage = new CancelInvocationMessage(null, invocationId);
sendHubMessageWithLock(cancelInvocationMessage);
connectionState.tryRemoveInvocation(invocationId);
subject.onComplete();
}
});
} finally {
this.state.unlock();
}
}
private void sendHubMessageWithLock(HubMessage message) {
this.state.lock();
try {
if (this.state.getHubConnectionState() != HubConnectionState.CONNECTED) {
throw new RuntimeException("Trying to send and message while the connection is not active.");
}
ByteBuffer serializedMessage = protocol.writeMessage(message);
if (message.getMessageType() == HubMessageType.INVOCATION) {
logger.debug("Sending {} message '{}'.", message.getMessageType().name(), ((InvocationMessage)message).getInvocationId());
} else if (message.getMessageType() == HubMessageType.STREAM_INVOCATION) {
logger.debug("Sending {} message '{}'.", message.getMessageType().name(), ((StreamInvocationMessage)message).getInvocationId());
} else {
logger.debug("Sending {} message.", message.getMessageType().name());
}
ConnectionState connectionState = this.state.getConnectionStateUnsynchronized(false);
connectionState.transport.send(serializedMessage).subscribeWith(CompletableSubject.create());
connectionState.resetKeepAlive();
} finally {
this.state.unlock();
}
}
View on GitHub (pinned to 294cab2f9b)
Solutions
- Ensure stop() fully completes before disposing resources or triggering further sends.
- If seen from the ping timer, verify there is no race between stop() and the timer (this is largely internal; report if reproducible in normal usage).
- Dispose upload-stream Observables when the connection closes so they stop emitting into a dead connection.
- Avoid calling connection methods after onClosed fires.
Example fix
// before: upload stream keeps emitting after disconnect
Observable<Data> src = hotObservable;
connection.send("Upload", src);
// src keeps emitting after connection.stop() -> sendHubMessageWithLock throws
// after: dispose the source on close
connection.onClosed(ex -> srcSubscription.dispose()); Defensive patterns
Strategy: validation
Validate before calling
// Internal guard; the practical user-side guard is to avoid emitting into a closed connection. // Dispose upload-stream sources on close. connection.onClosed(ex -> uploadStreamSubscription.dispose());
Type guard
boolean connectionActive = connection.getConnectionState() == HubConnectionState.CONNECTED;
Try / catch
// This error is internal and surfaces through transport/onError paths. Catch at the
// subscription boundary:
someObservable.subscribe(item -> {
if (connection.getConnectionState() == HubConnectionState.CONNECTED) {
connection.send("Upload", item);
}
}, error -> { /* log */ }); Prevention
- Dispose upload-stream Observables when the connection closes.
- Do not call HubConnection methods from onClosed except to schedule reconnect.
- Gate any callback that may fire post-disconnect on a state check.
- If reproducible from the ping timer under normal usage, report as a library bug.
When it happens
Trigger: Reached when sendHubMessageWithLock is invoked while state != CONNECTED: e.g. the ping timer fires after disconnect, an upload-stream's onNext races with stop(), or send/invoke/stream call paths reach here after the public guard already threw (defensive). Also when onClosed-triggered CloseMessage send is attempted mid-teardown.
Common situations: The keep-alive ping timer fires concurrently with stop() and attempts to send a Ping after state moved to DISCONNECTED. An Observable-based upload stream emits an item after the connection dropped. Internal cleanup paths sending CloseMessage during teardown.
Related errors
- HubConnection trying to negotiate when not in the CONNECTING
- The 'send' method cannot be called if the connection is not
- Invocation Id is already used
- Connection is not active.
- The HubConnection must be in the disconnected state to chang
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/1cf8c08b74c62329.
Report an issue: GitHub.