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

  1. Await connection.stop().blockingAwait() (or the Completable equivalent) before calling setBaseUrl.
  2. Check connection.getConnectionState() == HubConnectionState.DISCONNECTED before repointing.
  3. 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

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


AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06). Data as JSON: /api/errors/47753ddc86ba07c6. Report an issue: GitHub.