testcontainers/testcontainers-java · error · IllegalStateException
Unexpected scheme
Error message
Unexpected scheme %s
What it means
DockerClientProviderStrategy.test() validates a DOCKER_HOST by constructing a socket appropriate to its scheme. The code handles 'unix' and 'npipe' (plus tcp/localhost earlier in the switch); any other scheme (e.g. http://, https://, ftp://, or a typo) reaches the default branch and throws this IllegalStateException, failing the strategy's self-test.
Solutions
- Fix DOCKER_HOST to a supported scheme: tcp://host:2375, unix:///var/run/docker.sock, or npipe:////./pipe/docker_engine
- Unset DOCKER_HOST to let Testcontainers auto-detect the local Docker environment
- Verify with `echo $DOCKER_HOST` / `docker context ls` what the client is actually pointed at
Example fix
// before DOCKER_HOST=http://localhost:2375 // after DOCKER_HOST=tcp://localhost:2375 # or simply unset DOCKER_HOST and rely on auto-detection
Defensive patterns
Strategy: validation
Validate before calling
String dh = System.getenv("DOCKER_HOST");
if (dh != null) {
String scheme = java.net.URI.create(dh).getScheme();
if (scheme == null || !(scheme.equals("tcp") || scheme.equals("unix") || scheme.equals("npipe") || scheme.equals("http") || scheme.equals("https"))) {
throw new IllegalStateException("Unsupported DOCKER_HOST scheme: " + scheme + " in " + dh);
}
} Try / catch
try {
DockerClientFactory.instance().client();
} catch (IllegalStateException e) {
if (e.getMessage().startsWith("Unexpected scheme")) {
// unset or fix DOCKER_HOST and retry
}
throw e;
} Prevention
- Use only tcp://, unix://, or npipe:// schemes for DOCKER_HOST
- Prefer unsetting DOCKER_HOST and letting Testcontainers auto-detect
- Validate DOCKER_HOST in CI setup steps before running tests
When it happens
Trigger: DOCKER_HOST set to a value whose URI scheme is not one of tcp://, unix://, npipe:// — for example DOCKER_HOST=http://localhost:2375 or a malformed/misspelled scheme.
Common situations: Users copying docker CLI -H syntax (tcp://) incorrectly or using an http:// URL; DOCKER_HOST inherited from CI with a proxy-style URL; typos like 'unix:/' or quoted values with stray characters.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- Unknown DOCKER_HOST scheme
- DOCKER_HOST is not listening
- Changing startup timeout is not supported with mode
- Previous attempts to find a Docker environment failed. Will…
- containers are currently not supported
AI-assisted analysis of testcontainers/testcontainers-java@8e549514e3 (2026-09-12).
Data as JSON: /api/errors/fe930c835842653d.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/testcontainers/dockerclient/DockerClientProviderStrategy.java:198
}
socketProvider = socketFactory::createSocket;
socketAddress = new InetSocketAddress(dockerHost.getHost(), dockerHost.getPort());
break;
case "unix":
case "npipe":
if (!new File(dockerHost.getPath()).exists()) {
log.debug("DOCKER_HOST socket file '{}' does not exist", dockerHost.getPath());
return false;
}
socketProvider =
() -> {
switch (dockerHost.getScheme()) {
case "unix":
return UnixSocket.get(dockerHost.getPath());
case "npipe":
return new NamedPipeSocket(dockerHost.getPath());
default:
throw new IllegalStateException("Unexpected scheme " + dockerHost.getScheme());
}
};
socketAddress = new InetSocketAddress("localhost", 2375);
break;
default:
log.warn("Unknown DOCKER_HOST scheme {}, skipping the strategy test...", dockerHost.getScheme());
return true;
}
try (Socket socket = socketProvider.call()) {
Awaitility
.await()
.atMost(TestcontainersConfiguration.getInstance().getClientPingTimeout(), TimeUnit.SECONDS) // timeout after configured duration
.pollInterval(Duration.ofMillis(200)) // check state every 200ms
.pollDelay(Duration.ofSeconds(0)) // start checking immediately
.untilAsserted(() -> socket.connect(socketAddress));
return true;
} catch (Exception e) {View on GitHub (pinned to 8e549514e3)