{"record":{"id":"1cf8c08b74c62329","repo":"dotnet/aspnetcore","slug":"trying-to-send-and-message-while-the-connection-is","errorCode":null,"errorMessage":"Trying to send and message while the connection is not active.","messagePattern":"Trying to send and message while the connection is not active\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/SignalR/clients/java/signalr/core/src/main/java/com/microsoft/signalr/HubConnection.java","lineNumber":828,"sourceCode":"            sendInvocationMessage(method, args, invocationId, true);\n            return observable.doOnDispose(() -> {\n                if (subscriptionCount.decrementAndGet() == 0) {\n                    CancelInvocationMessage cancelInvocationMessage = new CancelInvocationMessage(null, invocationId);\n                    sendHubMessageWithLock(cancelInvocationMessage);\n                    connectionState.tryRemoveInvocation(invocationId);\n                    subject.onComplete();\n                }\n            });\n        } finally {\n            this.state.unlock();\n        }\n    }\n\n    private void sendHubMessageWithLock(HubMessage message) {\n        this.state.lock();\n        try {\n            if (this.state.getHubConnectionState() != HubConnectionState.CONNECTED) {\n                throw new RuntimeException(\"Trying to send and message while the connection is not active.\");\n            }\n            ByteBuffer serializedMessage = protocol.writeMessage(message);\n            if (message.getMessageType() == HubMessageType.INVOCATION) {\n                logger.debug(\"Sending {} message '{}'.\", message.getMessageType().name(), ((InvocationMessage)message).getInvocationId());\n            } else  if (message.getMessageType() == HubMessageType.STREAM_INVOCATION) {\n                logger.debug(\"Sending {} message '{}'.\", message.getMessageType().name(), ((StreamInvocationMessage)message).getInvocationId());\n            } else {\n                logger.debug(\"Sending {} message.\", message.getMessageType().name());\n            }\n\n            ConnectionState connectionState = this.state.getConnectionStateUnsynchronized(false);\n            connectionState.transport.send(serializedMessage).subscribeWith(CompletableSubject.create());\n            connectionState.resetKeepAlive();\n        } finally {\n            this.state.unlock();\n        }\n    }\n","sourceCodeStart":810,"sourceCodeEnd":846,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/SignalR/clients/java/signalr/core/src/main/java/com/microsoft/signalr/HubConnection.java#L810-L846","documentation":"sendHubMessageWithLock is the internal dispatch used by the public invoke/send/stream paths after they have built the HubMessage. It re-checks the state under the lock because the state may have transitioned away from CONNECTED between the caller's check and the actual transport.send. The message text contains a typo ('send and message').","triggerScenarios":"The connection drops between the outer invoke/send state check and this inner send: a close/transport-error callback fires on another thread and moves the state to DISCONNECTED before sendHubMessageWithLock acquires the lock.","commonSituations":"High-concurrency invoke during an unstable network; server-initiated close arriving while a burst of invocations is queued; stop() called concurrently with invoke() on another thread.","solutions":["Retry the invocation after the connection is re-established (subscribe to onReconnected).","Serialize invocations through a single queue drained only when state == CONNECTED so the window cannot open.","Avoid calling stop() concurrently with outstanding invocations - drain them first or let them fail fast."],"exampleFix":"// before\nhub.invoke(\"M\").subscribe(...);\n// concurrently on another thread:\nhub.stop();\n\n// after - stop only after invocations drain\nhub.invoke(\"M\").await();\nhub.stop().await();","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// This is an internal send; treat any 'connection is not active' failure\n// from invoke/send/stream as recoverable.\ntry {\n  hub.invoke(\"M\").await();\n} catch (RuntimeException e) {\n  if (e.getMessage().contains(\"connection is not active\")) {\n    // wait for onReconnected, then retry once\n  } else throw e;\n}","preventionTips":["Do not call stop() concurrently with outstanding invocations.","Drain or cancel in-flight invocations before stop().","Use a single-threaded outbound queue to eliminate the race window."],"tags":["signalr","java","state","concurrency","race-condition"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}