{"record":{"id":"47753ddc86ba07c6","repo":"dotnet/aspnetcore","slug":"the-hubconnection-must-be-in-the-disconnected-stat","errorCode":null,"errorMessage":"The HubConnection must be in the disconnected state to change the url.","messagePattern":"The HubConnection must be in the disconnected state to change the url\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/SignalR/clients/java/signalr/core/src/main/java/com/microsoft/signalr/HubConnection.java","lineNumber":219,"sourceCode":"        return this.state.getHubConnectionState();\n    }\n\n    // For testing only\n    String getBaseUrl() {\n        return this.baseUrl;\n    }\n\n    /**\n     * Sets a new url for the HubConnection.\n     * @param url The url to connect to.\n     */\n    public void setBaseUrl(String url) {\n        if (url == null || url.isEmpty()) {\n            throw new IllegalArgumentException(\"The HubConnection url must be a valid url.\");\n        }\n\n        if (this.state.getHubConnectionState() != HubConnectionState.DISCONNECTED) {\n            throw new IllegalStateException(\"The HubConnection must be in the disconnected state to change the url.\");\n        }\n\n        this.baseUrl = url;\n    }\n\n    /**\n     * Starts a connection to the server.\n     *\n     * @return A Completable that completes when the connection has been established.\n     */\n    public Completable start() {\n        CompletableSubject localStart = CompletableSubject.create();\n\n        this.state.lock.lock();\n        try {\n            if (this.state.getHubConnectionState() != HubConnectionState.DISCONNECTED) {\n                logger.debug(\"The connection is in the '{}' state. Waiting for in-progress start to complete or completing this start immediately.\", this.state.getHubConnectionState());\n                return this.state.getConnectionStateUnsynchronized(false).startTask;","sourceCodeStart":201,"sourceCodeEnd":237,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/294cab2f9b2e03af6b953820c7ab497c3c8b7ad9/src/SignalR/clients/java/signalr/core/src/main/java/com/microsoft/signalr/HubConnection.java#L201-L237","documentation":"An IllegalStateException thrown by setBaseUrl when the connection is not in the DISCONNECTED state. Changing the endpoint URL while CONNECTING or CONNECTED would corrupt in-flight negotiations and transport state, so the API forbids it. The connection must be fully stopped before repointing.","triggerScenarios":"Calling hubConnection.setBaseUrl(newUrl) before connection.stop() has completed, i.e. while getConnectionState() returns CONNECTING or CONNECTED.","commonSituations":"Attempting to 'rotate' or 'fail over' to a new endpoint on a transient error without first stopping the connection. Calling stop() but not awaiting its Completable before calling setBaseUrl. Reconnection logic that races with an in-progress start().","solutions":["Await connection.stop().blockingAwait() (or the Completable equivalent) before calling setBaseUrl.","Check connection.getConnectionState() == HubConnectionState.DISCONNECTED before repointing.","Reconsider fail-over design: stop fully, change URL, then start() again in sequence."],"exampleFix":"// before\nconnection.setBaseUrl(failoverUrl); // throws if still CONNECTED\n\n// after\nconnection.stop().blockingAwait();\nconnection.setBaseUrl(failoverUrl);\nconnection.start().blockingAwait();","handlingStrategy":"validation","validationCode":"if (connection.getConnectionState() == HubConnectionState.DISCONNECTED) {\n    connection.setBaseUrl(newUrl);\n} else {\n    // stop first, then set\n    connection.stop().blockingAwait();\n    connection.setBaseUrl(newUrl);\n}","typeGuard":null,"tryCatchPattern":"try {\n    connection.setBaseUrl(newUrl);\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"disconnected state\")) {\n        connection.stop().blockingAwait();\n        connection.setBaseUrl(newUrl);\n    } else { throw e; }\n}","preventionTips":["Treat endpoint fail-over as a full stop -> setBaseUrl -> start sequence, never an in-flight mutation.","Always await stop()'s Completable before changing configuration.","Encapsulate fail-over logic in a helper that checks state and serializes transitions."],"tags":["signalr","java","state-machine","lifecycle","url"],"analyzedSha":"294cab2f9b2e03af6b953820c7ab497c3c8b7ad9","analyzedAt":"2026-08-06T20:08:02.189Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}