{"record":{"id":"a5e71f4da3491af9","repo":"testcontainers/testcontainers-java","slug":"can-t-close-dockerclient","errorCode":null,"errorMessage":"Can't close DockerClient","messagePattern":"Can't close DockerClient","errorType":"exception","errorClass":"java.lang.RuntimeException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/testcontainers/images/builder/ImageFromDockerfile.java","lineNumber":169,"sourceCode":"                    transferable.transferTo(tarArchive, destination);\n                    bytesToDockerDaemon += transferable.getSize();\n                }\n                tarArchive.finish();\n            }\n\n            log.info(\"Transferred {} to Docker daemon\", FileUtils.byteCountToDisplaySize(bytesToDockerDaemon));\n            if (bytesToDockerDaemon > FileUtils.ONE_MB * 50) {\n                log.warn( // warn if >50MB sent to docker daemon\n                    \"A large amount of data was sent to the Docker daemon ({}). Consider using a .dockerignore file for better performance.\",\n                    FileUtils.byteCountToDisplaySize(bytesToDockerDaemon)\n                );\n            }\n\n            exec.awaitImageId();\n\n            return dockerImageName;\n        } catch (IOException e) {\n            throw new RuntimeException(\"Can't close DockerClient\", e);\n        }\n    }\n\n    protected void configure(BuildImageCmd buildImageCmd) {\n        buildImageCmd.withTags(Collections.singleton(getDockerImageName()));\n        this.dockerFilePath.ifPresent(buildImageCmd::withDockerfilePath);\n        this.dockerfile.ifPresent(p -> {\n                buildImageCmd.withDockerfile(p.toFile());\n                dependencyImageNames = new ParsedDockerfile(p).getDependencyImageNames();\n\n                if (dependencyImageNames.size() > 0) {\n                    // if we'll be pre-pulling images, disable the built-in pull as it is not necessary and will fail for\n                    // authenticated registries\n                    buildImageCmd.withPull(false);\n                }\n            });\n\n        this.buildArgs.forEach(buildImageCmd::withBuildArg);","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/testcontainers/testcontainers-java/blob/8e549514e3f01c57d70546fbb8599d138f3903e5/core/src/main/java/org/testcontainers/images/builder/ImageFromDockerfile.java#L151-L187","documentation":"ImageFromDockerfile.resolve() builds an image from a Dockerfile and must close the temporary DockerClient in a finally-ish path; if closing the client throws IOException it is rethrown as RuntimeException(\"Can't close DockerClient\"). It usually masks an I/O problem on the underlying docker client transport/streams.","triggerScenarios":"Calling imageId()/resolve() on an ImageFromDockerfile and the docker-java client's close() raises IOException — e.g. the transport/connection to the daemon is already broken after the build or awaitImageId() failed leaving streams in a bad state.","commonSituations":"Docker daemon dropped the connection during a long image build; build failed earlier causing streams to be closed twice; resource exhaustion (too many open files); abrupt daemon restart.","solutions":["Look at the cause (IOException) and earlier logs — the real failure is usually the image build itself, not the close","Ensure the Docker daemon stayed up during the build; retry the build","Check ulimit/file-descriptor limits if many containers/images are built in one JVM","Upgrade testcontainers/docker-java to pick up transport close-handling fixes","Catch and log this in test scaffolding so the original build failure isn't hidden"],"exampleFix":"// before\nString id = new ImageFromDockerfile().withDockerfileFromBuilder(b -> b.build()).get(); // masked IOException\n// after\n// fix the underlying build failure (e.g. invalid Dockerfile step) so close() succeeds\nString id = new ImageFromDockerfile()\n    .withDockerfileFromBuilder(b -> b.from(\"alpine:3.19\").run(\"echo hi\").build())\n    .get();","handlingStrategy":"try-catch","validationCode":"// ensure daemon is healthy before a long build\nnew ProcessBuilder(\"docker\",\"info\").inheritIO().start().waitFor() == 0;","typeGuard":"null","tryCatchPattern":"try {\n    String id = imageFromDockerfile.get();\n} catch (RuntimeException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"Can't close DockerClient\")) {\n        // the close-time IOException usually masks an earlier build/transport failure\n        throw new IllegalStateException(\"Image build failed; see cause: \" + e.getCause(), e);\n    }\n    throw e;\n}","preventionTips":["Read the cause chain — this error is almost always secondary to a build or transport failure","Keep the daemon running through long builds (disable sleep/timeout in CI)","Raise file-descriptor limits when building many images in one JVM","Keep testcontainers/docker-java updated for transport fixes"],"tags":["docker","docker-client","ioexception","image-build"],"backgroundTag":"file-close-failed","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"}