testcontainers/testcontainers-java · error · IllegalStateException
You should never close the global DockerClient!
Error message
You should never close the global DockerClient!
What it means
DockerClientFactory wraps the shared global DockerClient in a DockerClientDelegate whose close() throws this IllegalStateException. The client is a singleton shared across the JVM for all containers, so closing it would break every other consumer; the library deliberately forbids it.
Solutions
- Remove any close()/try-with-resources usage of the global DockerClient from DockerClientFactory.instance().client()
- If using a DI framework, register the client without a destroy/close method
- If you need a closable client, create your own DockerClient via DockerClientFactory or docker-java directly and close that one instead
Example fix
// before
try (DockerClient client = DockerClientFactory.instance().client()) {
client.inspectContainerCmd(id).exec();
}
// after
DockerClient client = DockerClientFactory.instance().client();
client.inspectContainerCmd(id).exec(); // never close the global client Defensive patterns
Strategy: try-catch
Validate before calling
if (client == DockerClientFactory.instance().client()) { throw new AssertionError("do not close the shared DockerClient"); } Type guard
static boolean isSharedGlobalClient(DockerClient c) { return c instanceof DockerClientDelegate; } Try / catch
try { client.close(); } catch (IllegalStateException e) { /* remove this close call entirely; never swallow into a retry */ } Prevention
- Never register DockerClientFactory.instance().client() as a Closeable/Disposable bean
- Never wrap the global client in try-with-resources
- Audit generic 'close everything' cleanup utilities for the DockerClient type
When it happens
Trigger: Calling close() on the DockerClient returned by DockerClientFactory.instance().client() (or any wrapper exposing the global client), e.g. in a finally block, try-with-resources, or a DI container disposing the client as a resource.
Common situations: Wrapping the client in try-with-resources by habit; shutting down a Spring/Guice context that registered the DockerClient as a Closeable bean; cleanup code that closes all Closeables in sight.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Check failed:
- Requested port ( ) is not mapped
- execInContainer can only be used while the Container is…
- Container startup failed for image
- This container does not support reuse
AI-assisted analysis of testcontainers/testcontainers-java@8e549514e3 (2026-09-12).
Data as JSON: /api/errors/72d69d804d24eb31.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/testcontainers/DockerClientFactory.java:205
if (cachedClientFailure != null) {
log.debug("There is a cached checks failure - throwing", cachedClientFailure);
throw cachedClientFailure;
}
if (client != null) {
return client;
}
final DockerClientProviderStrategy strategy = getOrInitializeStrategy();
client =
new DockerClientDelegate() {
@Getter
final DockerClient dockerClient = strategy.getDockerClient();
@Override
public void close() {
throw new IllegalStateException("You should never close the global DockerClient!");
}
};
log.info("Docker host IP address is {}", strategy.getDockerHostIpAddress());
Info dockerInfo = strategy.getInfo();
log.debug("Docker info: {}", dockerInfo.getRawValues());
Version version = client.versionCmd().exec();
log.debug("Docker version: {}", version.getRawValues());
activeApiVersion = version.getApiVersion();
String serverInfo =
"Connected to docker: \n" +
" Server Version: " +
dockerInfo.getServerVersion() +
"\n" +
" API Version: " +
activeApiVersion +
"\n" +View on GitHub (pinned to 8e549514e3)