testcontainers/testcontainers-java · error · IOException

Unable to create custom SSL factory instance

Error message

Unable to create custom SSL factory instance

What it means

When HttpWaitStrategy is configured with .usingTls().allowInsecure(), openConnection builds an SSLContext with a trust-all TrustManager and installs its socket factory on the connection. If SSLContext.getInstance("SSL") or sc.init(...) throws (NoSuchAlgorithmException / KeyManagementException), the strategy wraps it in this IOException. It is an environment/JRE problem, not an app problem.

Solutions

  1. Check available algorithms: Security.getAlgorithms("SSLContext") — use .usingTls() only if SSL/TLS is present
  2. Run on a standard, full JDK/JRE (e.g. official Temurin images)
  3. Upgrade the JVM/Testcontainers version; newer code may request "TLS" instead of "SSL"
  4. If TLS is not actually needed, drop .usingTls() and wait over plain HTTP

Example fix

// before
new HttpWaitStrategy().usingTls().allowInsecure().forPort(8443);
// after
// only if the endpoint really is HTTPS; otherwise wait over HTTP
new HttpWaitStrategy().forPort(8080);
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure the JVM can create the SSL context before configuring TLS waits
if (!java.security.Security.getAlgorithms("SSLContext").stream()
        .anyMatch(a -> a.equalsIgnoreCase("SSL") || a.equalsIgnoreCase("TLS"))) {
    throw new IllegalStateException("No SSLContext provider available; avoid .usingTls()");
}

Try / catch

try {
    container.waitingFor(new HttpWaitStrategy().usingTls().allowInsecure()).start();
} catch (ContainerLaunchException e) {
    Throwable root = e;
    while (root.getCause() != null) root = root.getCause();
    if (root instanceof NoSuchAlgorithmException || root instanceof KeyManagementException) {
        // fall back to plain HTTP wait or fix the JRE
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling .usingTls(true).allowInsecure(true) on a JRE lacking the requested SSL algorithm or failing key-manager initialization (restricted crypto policy, broken security provider, unusual JRE build).

Common situations: Running on minimal/custom JRE builds (jlink images) missing crypto providers; ancient or exotic JVMs without 'SSL' algorithm; corporate JVM with stripped security providers.

Understand the failure class

Related errors


AI-assisted analysis of testcontainers/testcontainers-java@8e549514e3 (2026-09-12). Data as JSON: /api/errors/bd9eb67e14593315. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/testcontainers/containers/wait/strategy/HttpWaitStrategy.java:369

                        @Override
                        public void checkServerTrusted(X509Certificate[] chain, String authType, Socket socket) {}

                        @Override
                        public void checkClientTrusted(X509Certificate[] chain, String authType, SSLEngine engine) {}

                        @Override
                        public void checkServerTrusted(X509Certificate[] chain, String authType, SSLEngine engine) {}
                    },
                };

                try {
                    // Create custom SSL context and set the "trust all certificates" trust manager
                    final SSLContext sc = SSLContext.getInstance("SSL");
                    sc.init(new KeyManager[0], trustAllCerts, new SecureRandom());
                    connection.setSSLSocketFactory(sc.getSocketFactory());
                } catch (final NoSuchAlgorithmException | KeyManagementException ex) {
                    throw new IOException("Unable to create custom SSL factory instance", ex);
                }
            }

            return connection;
        } else {
            return (HttpURLConnection) new URL(uri).openConnection();
        }
    }

    /**
     * Build the URI on which to check if the container is ready.
     *
     * @param livenessCheckPort the liveness port
     * @return the liveness URI
     */
    private URI buildLivenessUri(int livenessCheckPort) {
        final String scheme = (tlsEnabled ? "https" : "http") + "://";
        final String host = waitStrategyTarget.getHost();

View on GitHub (pinned to 8e549514e3)