dotnet/aspnetcore · error · IllegalStateException
The HubConnection must be in the disconnected state to chang
Error message
The HubConnection must be in the disconnected state to change the url.
What it means
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.
Source
Thrown at src/SignalR/clients/java/signalr/core/src/main/java/com/microsoft/signalr/HubConnection.java:219
return this.state.getHubConnectionState();
}
// For testing only
String getBaseUrl() {
return this.baseUrl;
}
/**
* Sets a new url for the HubConnection.
* @param url The url to connect to.
*/
public void setBaseUrl(String url) {
if (url == null || url.isEmpty()) {
throw new IllegalArgumentException("The HubConnection url must be a valid url.");
}
if (this.state.getHubConnectionState() != HubConnectionState.DISCONNECTED) {
throw new IllegalStateException("The HubConnection must be in the disconnected state to change the url.");
}
this.baseUrl = url;
}
/**
* Starts a connection to the server.
*
* @return A Completable that completes when the connection has been established.
*/
public Completable start() {
CompletableSubject localStart = CompletableSubject.create();
this.state.lock.lock();
try {
if (this.state.getHubConnectionState() != HubConnectionState.DISCONNECTED) {
logger.debug("The connection is in the '{}' state. Waiting for in-progress start to complete or completing this start immediately.", this.state.getHubConnectionState());
return this.state.getConnectionStateUnsynchronized(false).startTask;View on GitHub (pinned to 294cab2f9b)
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.
Example fix
// before connection.setBaseUrl(failoverUrl); // throws if still CONNECTED // after connection.stop().blockingAwait(); connection.setBaseUrl(failoverUrl); connection.start().blockingAwait();
Defensive patterns
Strategy: validation
Validate before calling
if (connection.getConnectionState() == HubConnectionState.DISCONNECTED) {
connection.setBaseUrl(newUrl);
} else {
// stop first, then set
connection.stop().blockingAwait();
connection.setBaseUrl(newUrl);
} Try / catch
try {
connection.setBaseUrl(newUrl);
} catch (IllegalStateException e) {
if (e.getMessage().contains("disconnected state")) {
connection.stop().blockingAwait();
connection.setBaseUrl(newUrl);
} else { throw e; }
} Prevention
- 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.
When it happens
Trigger: Calling hubConnection.setBaseUrl(newUrl) before connection.stop() has completed, i.e. while getConnectionState() returns CONNECTING or CONNECTED.
Common situations: 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().
Related errors
- The 'send' method cannot be called if the connection is not
- The 'invoke' method cannot be called if the connection is no
- The 'stream' method cannot be called if the connection is no
- Connection is not active.
- The HubConnection url must be a valid url.
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/47753ddc86ba07c6.
Report an issue: GitHub.