testcontainers/testcontainers-java · error · IllegalStateException

Failed to process JAR file when extracting classpath…

Error message

Failed to process JAR file when extracting classpath resource: <hostPath>

What it means

MountableFile wraps classpath resources so they can be mounted into containers. When it must extract a resource that lives inside a JAR (e.g. from a fat jar) to a temp location, any IOException while reading the JAR or copying the entry is wrapped in this IllegalStateException. It means Testcontainers could not materialize the classpath resource on the host filesystem, not that the resource itself is necessarily missing (missing resources fail earlier with IllegalArgumentException).

Solutions

  1. Rebuild the artifact/JAR (mvn clean package or gradle clean build) to rule out a corrupt jar
  2. Ensure the temp directory (java.io.tmpdir) exists, is writable, and has free space
  3. Verify the resource exists on the classpath; if it is a directory of files in the jar, confirm the path points to an entry the code can copy
  4. As a workaround, copy the resource out of the jar yourself and mount it with MountableFile.forHostFile(...)

Example fix

// before
MountableFile.forClasspathResource("config/app.conf"); // fails when inside nested/fat jar
// after
File extracted = extractViaClassloader("config/app.conf"); // write to your own temp file
MountableFile.forHostFile(extracted);
Defensive patterns

Strategy: validation

Validate before calling

String path = "config/app.conf";
if (MountableFile.class.getClassLoader().getResource(path) == null)
    throw new IllegalStateException("Classpath resource missing: " + path);
// also verify tmpdir is writable:
File tmp = new File(System.getProperty("java.io.tmpdir"));
if (!tmp.canWrite()) throw new IllegalStateException("Temp dir not writable: " + tmp);

Type guard

boolean isExtractable(String path) {
    URL u = Thread.currentThread().getContextClassLoader().getResource(path);
    return u != null && List.of("jar", "file").contains(u.getProtocol());
}

Try / catch

try {
    MountableFile.forClasspathResource(path);
} catch (IllegalStateException e) {
    // fallback: extract manually via classloader and mount a host file
}

Prevention

When it happens

Trigger: Calling MountableFile.forClasspathResource(...) (directly or via withClasspathResourceMapping / copyFileToContainer) where the resource is inside a JAR, and copyFromJarToLocation throws IOException: corrupt/unreadable JAR, entry is a directory with IO problems, disk full, or temp dir not writable.

Common situations: Running tests from a Spring Boot fat jar or shaded jar where resources are nested jars; read-only or full temp directories; JAR corrupted by partial builds; running under a security manager or restricted filesystem that blocks reading the jar.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of testcontainers/testcontainers-java@8e549514e3 (2026-09-12). Data as JSON: /api/errors/30f6f5ba50777290. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/testcontainers/utility/MountableFile.java:257

        String internalPath = hostPath.replaceAll("[^!]*!/", "");

        try (JarFile jarFile = new JarFile(urldecodedJarPath)) {
            Enumeration<JarEntry> entries = jarFile.entries();

            while (entries.hasMoreElements()) {
                JarEntry entry = entries.nextElement();
                final String name = entry.getName();
                if (name.startsWith(internalPath)) {
                    log.debug(
                        "Copying classpath resource(s) from {} to {} to permit Docker to bind",
                        hostPath,
                        tmpLocation
                    );
                    copyFromJarToLocation(jarFile, entry, internalPath, tmpLocation);
                }
            }
        } catch (IOException e) {
            throw new IllegalStateException(
                "Failed to process JAR file when extracting classpath resource: " + hostPath,
                e
            );
        }

        // Mark temporary files/dirs for deletion at JVM shutdown
        deleteOnExit(tmpLocation.toPath());

        try {
            return tmpLocation.getCanonicalPath();
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }
    }

    private File createTempDirectory() {
        try {
            if (SystemUtils.IS_OS_MAC) {

View on GitHub (pinned to 8e549514e3)