testcontainers/testcontainers-java · error · IllegalStateException

copyFileToContainer can only be used with created / running…

Error message

copyFileToContainer can only be used with created / running container

What it means

copyFileToContainer streams a file into the container via the Docker API, which requires an existing container ID. If getContainerId() is null (container never created/started) it throws IllegalStateException, since the copy target does not exist yet.

Solutions

  1. Start the container first: call start() (or createContainer in newer APIs) before copyFileToContainer
  2. Alternatively use withCopyFileToContainer(...) as a builder modifier, which Testcontainers applies after container creation automatically
  3. Ensure you're not operating on a fresh GenericContainer object in a helper method
  4. Verify container state with isCreated()/isRunning() if the lifecycle is dynamic

Example fix

// before
GenericContainer c = new GenericContainer<>("alpine:3");
c.copyFileToContainer(Transferable.of(bytes), "/tmp/a.txt");
c.start();
// after
GenericContainer c = new GenericContainer<>("alpine:3")
    .withCopyFileToContainer(Transferable.of(bytes), "/tmp/a.txt");
c.start();
Defensive patterns

Strategy: validation

Validate before calling

if (container.getContainerId() == null) throw new IllegalStateException("start() the container before copyFileToContainer");

Try / catch

try { container.copyFileToContainer(t, path); } catch (IllegalStateException e) { if (e.getMessage().startsWith("copyFileToContainer")) { container.start(); container.copyFileToContainer(t, path); } else { throw e; } }

Prevention

When it happens

Trigger: Invoking copyFileToContainer(...) on a GenericContainer instance before start() (or before any start attempt created the container).

Common situations: Copying config files in a test setup method before starting the container; copy calls that were reordered after a refactor; containers created with a lifecycle that never reached the created state.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at core/src/main/java/org/testcontainers/containers/ContainerState.java:345

                "folder-like containerPath in copyFileToContainer is deprecated, please explicitly specify a file path"
            );
            copyFileToContainer((Transferable) mountableFile, containerPath + sourceFile.getName());
        } else {
            copyFileToContainer((Transferable) mountableFile, containerPath);
        }
    }

    /**
     *
     * Copies a file to the container.
     *
     * @param transferable file which is copied into the container
     * @param containerPath destination path inside the container
     */
    @SneakyThrows({ IOException.class, InterruptedException.class })
    default void copyFileToContainer(Transferable transferable, String containerPath) {
        if (getContainerId() == null) {
            throw new IllegalStateException("copyFileToContainer can only be used with created / running container");
        }

        try (
            PipedOutputStream pipedOutputStream = new PipedOutputStream();
            PipedInputStream pipedInputStream = new PipedInputStream(pipedOutputStream);
            TarArchiveOutputStream tarArchive = new TarArchiveOutputStream(pipedOutputStream)
        ) {
            Thread thread = new Thread(() -> {
                try {
                    tarArchive.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);
                    tarArchive.setBigNumberMode(TarArchiveOutputStream.BIGNUMBER_POSIX);

                    transferable.transferTo(tarArchive, containerPath);
                } finally {
                    IOUtils.closeQuietly(tarArchive);
                }
            });

View on GitHub (pinned to 8e549514e3)