{"record":{"id":"35749e0e95dccb2a","repo":"testcontainers/testcontainers-java","slug":"failed-to-detect-protocol-via-curl-both-https-and-http","errorCode":null,"errorMessage":"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","messagePattern":"Failed to detect protocol via curl\\. Both HTTPS and HTTP probes failed\\. HTTPS probe - exit code: (.+?), stdout: (.+?), stderr: (.+?); HTTP probe - exit code: (.+?), stdout: (.+?), stderr: (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"modules/elasticsearch/src/main/java/org/testcontainers/elasticsearch/ElasticsearchContainer.java","lineNumber":342,"sourceCode":"                    \"-sS\",\n                    \"--connect-timeout\",\n                    \"2\",\n                    \"--max-time\",\n                    \"4\",\n                    \"-o\",\n                    \"/dev/null\",\n                    \"-w\",\n                    \"%{http_code}\",\n                    \"http://localhost:\" + ELASTICSEARCH_DEFAULT_PORT + \"/\"\n                );\n            if (httpResult.getExitCode() == 0 && !\"000\".equals(httpResult.getStdout().trim())) {\n                return \"http\";\n            }\n        } catch (Exception e) {\n            throw new RuntimeException(\"Failed to detect protocol via curl\", e);\n        }\n\n        throw new RuntimeException(\n            String.format(\n                \"Failed to detect protocol via curl. Both HTTPS and HTTP probes failed. \" +\n                \"HTTPS probe - exit code: %d, stdout: %s, stderr: %s; \" +\n                \"HTTP probe - exit code: %d, stdout: %s, stderr: %s\",\n                httpsResult.getExitCode(),\n                httpsResult.getStdout(),\n                httpsResult.getStderr(),\n                httpResult.getExitCode(),\n                httpResult.getStdout(),\n                httpResult.getStderr()\n            )\n        );\n    }\n\n    // The TransportClient will be removed in Elasticsearch 8. No need to expose this port anymore in the future.\n    @Deprecated\n    public InetSocketAddress getTcpHost() {\n        return new InetSocketAddress(getHost(), getMappedPort(ELASTICSEARCH_DEFAULT_TCP_PORT));","sourceCodeStart":324,"sourceCodeEnd":360,"githubUrl":"https://github.com/testcontainers/testcontainers-java/blob/8e549514e3f01c57d70546fbb8599d138f3903e5/modules/elasticsearch/src/main/java/org/testcontainers/elasticsearch/ElasticsearchContainer.java#L324-L360","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\nelasticsearch.start();\nString url = elasticsearch.getHttpHostAddress(); // throws if ES not ready\n// after\nelasticsearch.withStartupTimeout(Duration.ofMinutes(3))\n    .waitingFor(Wait.forHttp(\"/\").forStatusCodeAllowingRedirects());\nelasticsearch.start();\nString url = elasticsearch.getHttpHostAddress();","handlingStrategy":"retry","validationCode":"if (!container.isRunning()) { throw new IllegalStateException(\"Elasticsearch container not running\"); }","typeGuard":null,"tryCatchPattern":"try { String addr = es.getHttpHostAddress(); } catch (RuntimeException e) { System.err.println(es.getLogs()); throw e; }","preventionTips":["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."],"tags":["elasticsearch","testcontainers","startup","connectivity"],"backgroundTag":"connection-refused","analyzedSha":"8e549514e3f01c57d70546fbb8599d138f3903e5","analyzedAt":"2026-09-12T14:56:41.227Z","contentChangedAt":"2026-09-12T14:56:41.227Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}