dotnet/aspnetcore · error · IllegalArgumentException

A valid url is required.

Error message

A valid url is required.

What it means

Thrown by the HubConnection constructor when url is null or empty. This is the package-private constructor invoked by HubConnectionBuilder; users typically hit it through the builder if they somehow bypass withUrl, or when constructing HubConnection directly in tests. Distinct from setBaseUrl (175) which is the post-construction setter.

Solutions

  1. Always build HubConnection via HubConnectionBuilder.create(url) so withUrl/withUrl validation runs first.
  2. Null-check the url at the configuration boundary and fail with a clearer message before reaching the constructor.
  3. In tests, pass a dummy URL (http://localhost:0) rather than null.

Example fix

// before (test)
HubConnection conn = new HubConnection(null, transport, ...); // throws

// after
HubConnection conn = HubConnectionBuilder.create("http://localhost:5050/hub").build();
Defensive patterns

Strategy: validation

Validate before calling

HubConnection build(String url) {
  if (url == null || url.isEmpty()) {
    throw new IllegalArgumentException("hub url is required");
  }
  return HubConnectionBuilder.create(url).build();
}

Type guard

boolean isValidHubUrl(String url) {
  return url != null && !url.isEmpty();
}

Try / catch

try {
  return HubConnectionBuilder.create(url).build();
} catch (IllegalArgumentException e) {
  if ("A valid url is required.".equals(e.getMessage())) {
    // supply a valid url and rebuild
  } else throw e;
}

Prevention

When it happens

Trigger: HubConnection is constructed (directly or via a builder path) with url == null or url.isEmpty(). In normal builder usage withUrl guards this earlier (162), so this throw surfaces for direct constructor use, custom builders, or reflection-based test helpers.

Common situations: Tests that new HubConnection(...) directly with a null url; a custom builder/wrapper that forgets to set the url; a configuration load that returns null and the wrapper passes it straight through.

Related errors


AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11). Data as JSON: /api/errors/6317061cb5c699a0. Report an issue: GitHub.

Appendix: source

Thrown at src/SignalR/clients/java/signalr/core/src/main/java/com/microsoft/signalr/HubConnection.java:128

        }
        return null;
    }

    // For testing purposes
    void setTickRate(long tickRateInMilliseconds) {
        this.tickRate = tickRateInMilliseconds;
    }

    // For testing purposes
    Transport getTransport() {
        return this.state.getConnectionState().transport;
    }

    HubConnection(String url, Transport transport, boolean skipNegotiate, HttpClient httpClient, HubProtocol protocol,
                  Single<String> accessTokenProvider, long handshakeResponseTimeout, Map<String, String> headers, TransportEnum transportEnum,
                  Action1<OkHttpClient.Builder> configureBuilder, long serverTimeout, long keepAliveInterval) {
        if (url == null || url.isEmpty()) {
            throw new IllegalArgumentException("A valid url is required.");
        }

        this.state = new ReconnectingConnectionState(this.logger);
        this.baseUrl = url;
        this.protocol = protocol;

        if (accessTokenProvider != null) {
            this.accessTokenProvider = accessTokenProvider;
        } else {
            this.accessTokenProvider = Single.just("");
        }

        if (httpClient != null) {
            this.httpClient = httpClient;
        } else {
            this.httpClient = new DefaultHttpClient(configureBuilder);
        }

View on GitHub (pinned to 3600ca084e)