{"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":"validation","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/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/SignalR/clients/java/signalr/core/src/main/java/com/microsoft/signalr/HubConnection.java#L201-L237","documentation":"Thrown by HubConnection.setBaseUrl when the connection is not in the DISCONNECTED state. Changing the base URL while connected would corrupt in-flight invocations and transport state, so the client forbids it. The check runs after the null/empty URL check (175).","triggerScenarios":"Calling hubConnection.setBaseUrl(newUrl) after start() has connected (or while connecting/reconnecting) and before stop() completes. HubConnectionState.DISCONNECTED is required.","commonSituations":"Redirect/relocate logic triggered by a server message while the connection is still live; calling setBaseUrl in an onConnected handler; reconnect logic that races and runs setBaseUrl before the previous connection fully stopped.","solutions":["Always stop() the connection and await its completion before calling setBaseUrl.","Gate the redirect logic: if (conn.getConnectionState() == HubConnectionState.DISCONNECTED) conn.setBaseUrl(newUrl); else queue and apply after stop.","For server-driven redirects, rely on the built-in negotiate redirect handling rather than setBaseUrl during an active connection."],"exampleFix":"// before\nconn.start().blockingAwait();\nconn.setBaseUrl(newUrl); // connected -> throws\n\n// after\nconn.stop().blockingAwait();\nconn.setBaseUrl(newUrl);\nconn.start().blockingAwait();","handlingStrategy":"validation","validationCode":"void relocate(HubConnection conn, String newUrl) {\n  if (conn.getConnectionState() != HubConnectionState.DISCONNECTED) {\n    conn.stop().blockingAwait();\n  }\n  conn.setBaseUrl(newUrl);\n}","typeGuard":"boolean isDisconnected(HubConnection conn) {\n  return conn.getConnectionState() == HubConnectionState.DISCONNECTED;\n}","tryCatchPattern":"try {\n  conn.setBaseUrl(newUrl);\n} catch (IllegalStateException e) {\n  if (\"The HubConnection must be in the disconnected state to change the url.\".equals(e.getMessage())) {\n    conn.stop().blockingAwait();\n    conn.setBaseUrl(newUrl);\n  } else throw e;\n}","preventionTips":["Always stop() and await completion before setBaseUrl.","Gate relocation on DISCONNECTED state.","Prefer the built-in negotiate redirect handling over manual setBaseUrl while live."],"tags":["signalr","java","state-machine","connection-lifecycle","url"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}