karatelabs/karate · error · IllegalArgumentException

URI cannot be null

Error message

URI cannot be null

What it means

WsClientOptions.Builder's constructor validates its URI argument and throws IllegalArgumentException when null is passed. The builder cannot construct meaningful WebSocket client options without a target URI, so it fails fast at builder-creation time rather than at connect time.

Solutions

  1. Pass a non-null URI, e.g. URI.create("ws://host:port/path")
  2. Validate/parse the URL from config before building options and fail with a clear config error
  3. Use Objects.requireNonNull(uri, "...") at your own call site to surface which config key was missing

Example fix

// before
String url = config.get("ws.url"); // null
WsClientOptions.builder(URI.create(url));
// after
String url = Objects.requireNonNull(config.get("ws.url"), "ws.url not configured");
WsClientOptions.builder(URI.create(url));
Defensive patterns

Strategy: validation

Validate before calling

if (uri == null) throw new IllegalArgumentException("ws uri not configured");

Type guard

boolean ok = uri != null && ("ws".equals(uri.getScheme()) || "wss".equals(uri.getScheme()));

Try / catch

try { WsClientOptions.builder(uri); } catch (IllegalArgumentException e) { throw new ConfigException("invalid websocket uri: " + e.getMessage(), e); }

Prevention

When it happens

Trigger: Calling WsClientOptions.builder(null), or passing a variable/expression that resolved to null (e.g. missing config value) into the builder.

Common situations: Reading the ws URL from config/env and getting null because the key is missing; conditional logic that skips URL assignment; refactoring that changed a method to return null on failure.

Related errors


AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12). Data as JSON: /api/errors/777b48f5b590c4b8. Report an issue: GitHub.

Appendix: source

Thrown at karate-core/src/main/java/io/karatelabs/http/WsClientOptions.java:170

    public static class Builder {

        private final URI uri;
        private Map<String, String> headers;
        private String subProtocol;
        private boolean compression = false;
        private int maxPayloadSize = HttpUtils.MEGABYTE;
        private Duration connectTimeout = Duration.ofSeconds(30);
        private Duration pingInterval = Duration.ofSeconds(30);
        private boolean trustAllCerts = true;
        private SslContext sslContext;
        private ExecutorService callbackExecutor;
        private Consumer<WsFrame> messageListener;
        private Runnable closeListener;
        private Consumer<Throwable> errorListener;

        private Builder(URI uri) {
            if (uri == null) {
                throw new IllegalArgumentException("URI cannot be null");
            }
            this.uri = uri;
        }

        public Builder headers(Map<String, String> headers) {
            this.headers = headers;
            return this;
        }

        public Builder header(String name, String value) {
            if (this.headers == null) {
                this.headers = new LinkedHashMap<>();
            }
            this.headers.put(name, value);
            return this;
        }

        /** The WebSocket subprotocol to negotiate during the handshake (Sec-WebSocket-Protocol). */

View on GitHub (pinned to a22eb90246)