elastic/elasticsearch · error · IllegalStateException

SSL trust has been configured, but [{}] is not a 'https' URL

Error message

SSL trust has been configured, but [{}] is not a 'https' URL

What it means

WaitForHttpResource.configureSslContext() throws when an SSLContext has been configured on the resource but the URL is not an `HttpsURLConnection` (i.e. the URL scheme is `http://`, not `https://`). SSL trust is meaningless over plaintext HTTP, so the build refuses rather than silently sending credentials in the clear or no-op'ing the SSL setup.

Source

Thrown at build-tools/src/main/java/org/elasticsearch/gradle/testclusters/WaitForHttpResource.java:142

        } else {
            throw new IOException(response + " " + connection.getResponseMessage());
        }
    }

    HttpURLConnection buildConnection(SSLContext ssl) throws IOException {
        final HttpURLConnection connection = (HttpURLConnection) this.url.openConnection();
        configureSslContext(connection, ssl);
        configureBasicAuth(connection);
        connection.setRequestMethod("GET");
        return connection;
    }

    private void configureSslContext(HttpURLConnection connection, SSLContext ssl) {
        if (ssl != null) {
            if (connection instanceof HttpsURLConnection) {
                ((HttpsURLConnection) connection).setSSLSocketFactory(ssl.getSocketFactory());
            } else {
                throw new IllegalStateException("SSL trust has been configured, but [" + url + "] is not a 'https' URL");
            }
        }
    }

    private void configureBasicAuth(HttpURLConnection connection) {
        if (username != null) {
            if (password == null) {
                throw new IllegalStateException("Basic Auth user [" + username + "] has been set, but no password has been configured");
            }
            connection.setRequestProperty(
                "Authorization",
                "Basic " + Base64.getEncoder().encodeToString((username + ":" + password).getBytes(StandardCharsets.UTF_8))
            );
        }
    }
}

View on GitHub (pinned to db6a809a66)

Solutions

  1. Change the URL scheme to `https://` so the connection is an `HttpsURLConnection`.
  2. Or, if TLS is genuinely not needed, remove the SSLContext configuration (and disable security on the cluster).
  3. Construct the readiness URL from the cluster's HTTP settings to inherit the correct scheme automatically.

Example fix

// before
waitResource.url = 'http://localhost:9200/_cluster/health'
waitResource.sslContext = ssl
// after
waitResource.url = 'https://localhost:9200/_cluster/health'
waitResource.sslContext = ssl
Defensive patterns

Strategy: validation

Validate before calling

if (sslContext != null && !"https".equalsIgnoreCase(url.getProtocol())) {
  throw new IllegalStateException(
    "SSL configured for non-https URL " + url + "; switch to https:// or drop the SSLContext.");
}

Prevention

When it happens

Trigger: Setting `.sslContext(...)` or enabling TLS on a WaitForHttpResource whose `url` field is an `http://...` URL. The resource is used by testclusters to poll node readiness over HTTP.

Common situations: Security/TLS enabled on the cluster but the readiness URL constructed with `http://`; copy-pasting a URL template and forgetting to switch the scheme; defaulting the URL to http while conditionally adding SSL config.

Understand the failure class

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/c033d34b5eae7f35. Report an issue: GitHub.