testcontainers/testcontainers-java · error · RuntimeException
Failed to detect protocol via curl. Both HTTPS and HTTP…
Error message
Failed to detect protocol via curl. Both HTTPS and HTTP probes failed. HTTPS probe - exit code: %d, stdout: %s, stderr: %s; HTTP probe - exit code: %d, stdout: %s, stderr: %s
What it means
getHttpScheme() runs two curl probes inside the Elasticsearch container (HTTPS with -k, then HTTP) against localhost:9200 and reads the HTTP status code. If neither probe yields an HTTP response (exit code 0 and http_code != '000'), it throws this RuntimeException containing both probes' exit codes, stdout and stderr for diagnosis.
Solutions
- Inspect the container logs (container.getLogs()) to see why Elasticsearch is not responding.
- Increase/fix the wait strategy (Wait.forHttp("/") with enough startup timeout) so getHttpScheme is only called when ES is ready.
- Check host settings: vm.max_map_count >= 262144 and sufficient memory for the container.
- Read the HTTPS/HTTP probe details in the message: exit code and stderr indicate whether TLS handshake or connection itself failed.
- Use default images (docker.elastic.co/elasticsearch/elasticsearch) where security/scheme behavior matches what getHttpScheme expects.
Example fix
// before
elasticsearch.start();
String url = elasticsearch.getHttpHostAddress(); // throws if ES not ready
// after
elasticsearch.withStartupTimeout(Duration.ofMinutes(3))
.waitingFor(Wait.forHttp("/").forStatusCodeAllowingRedirects());
elasticsearch.start();
String url = elasticsearch.getHttpHostAddress(); Defensive patterns
Strategy: retry
Validate before calling
if (!container.isRunning()) { throw new IllegalStateException("Elasticsearch container not running"); } Try / catch
try { String addr = es.getHttpHostAddress(); } catch (RuntimeException e) { System.err.println(es.getLogs()); throw e; } Prevention
- Always set a proper wait strategy (Wait.forHttp("/")) with adequate startupTimeout.
- Verify vm.max_map_count >= 262144 on the Docker host.
- Give the container enough memory; ES killed by OOM looks like a probe failure.
- Check container.getLogs() when the error includes exit code 000 for both probes.
- Pin supported Elasticsearch image versions.
When it happens
Trigger: Calling getHttpScheme()/url/scheme/getHttpHostAddress after the container reports running, but Elasticsearch is not accepting connections on port 9200 yet (still starting, crashed, OOM-killed, or bound to a different port).
Common situations: Elasticsearch taking longer than the wait strategy allows to start; vm.max_map_count too low causing ES startup failure; memory limits killing the ES process; wrong security-enabled setting so the probe misses the actual listener.
Understand the failure class
Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.
Related errors
- Couchbase /pools did not return valid JSON
- Couchbase /pools/default/nodeServices did not return valid…
- message: response, body=body
- Failed to detect protocol via curl
- withReuse(true) is not supported for KibanaContainer in…
AI-assisted analysis of testcontainers/testcontainers-java@8e549514e3 (2026-09-12).
Data as JSON: /api/errors/35749e0e95dccb2a.
Report an issue: GitHub.
Appendix: source
Thrown at modules/elasticsearch/src/main/java/org/testcontainers/elasticsearch/ElasticsearchContainer.java:342
"-sS",
"--connect-timeout",
"2",
"--max-time",
"4",
"-o",
"/dev/null",
"-w",
"%{http_code}",
"http://localhost:" + ELASTICSEARCH_DEFAULT_PORT + "/"
);
if (httpResult.getExitCode() == 0 && !"000".equals(httpResult.getStdout().trim())) {
return "http";
}
} catch (Exception e) {
throw new RuntimeException("Failed to detect protocol via curl", e);
}
throw new RuntimeException(
String.format(
"Failed to detect protocol via curl. Both HTTPS and HTTP probes failed. " +
"HTTPS probe - exit code: %d, stdout: %s, stderr: %s; " +
"HTTP probe - exit code: %d, stdout: %s, stderr: %s",
httpsResult.getExitCode(),
httpsResult.getStdout(),
httpsResult.getStderr(),
httpResult.getExitCode(),
httpResult.getStdout(),
httpResult.getStderr()
)
);
}
// The TransportClient will be removed in Elasticsearch 8. No need to expose this port anymore in the future.
@Deprecated
public InetSocketAddress getTcpHost() {
return new InetSocketAddress(getHost(), getMappedPort(ELASTICSEARCH_DEFAULT_TCP_PORT));View on GitHub (pinned to 8e549514e3)