testcontainers/testcontainers-java · critical · ContainerLaunchException
Container startup failed for image
Error message
Container startup failed for image ${dockerImageName} What it means
GenericContainer.doStart wraps any exception raised while creating/starting the container in a ContainerLaunchException with this message, using the Docker image name for context. It is a wrapper: the root cause (nested exception) holds the actual failure — image pull failure, port conflict, startup check failure, wait strategy timeout, etc.
Solutions
- Read the 'Caused by' chain of this ContainerLaunchException to find the root cause.
- Verify the image name/tag is correct and pullable (docker pull <image>).
- Check the Docker daemon is up and reachable (docker info).
- Increase the wait strategy timeout if the container starts slowly: container.waitingFor(Wait.forLogMessage(...)).withStartupTimeout(Duration.ofMinutes(2)).
- Inspect container stdout/stderr logs printed by Testcontainers just before this exception for the real startup error.
Example fix
// before
try {
container.start();
} catch (ContainerLaunchException ignored) { }
// after
try {
container.start();
} catch (ContainerLaunchException e) {
// log the full cause chain to see the real startup failure
logger.error("Container startup failed", e);
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
boolean dockerUp = java.util.Optional.ofNullable(
new ProcessBuilder("docker", "info").start().waitFor() == 0).orElse(false); Type guard
null
Try / catch
try {
container.start();
} catch (ContainerLaunchException e) {
// root cause is in the cause chain — log it fully before retrying or failing
logger.error("Startup failed for {}", container.getDockerImageName(), e);
throw e;
} Prevention
- Check docker daemon health in CI before the test phase.
- Pin image tags explicitly instead of :latest.
- Pre-pull images in a CI setup step to catch auth/pull issues early.
- Give wait strategies generous startup timeouts for heavy images.
When it happens
Trigger: Any failure inside container.start() → doStart(): image not found/unpullable, Ryuk or Docker unavailable, startup check failing (container never reaches running state), wait strategy timeout, reuse validation failing, or InspectContainerResponse problems during tryStart.
Common situations: Typo in image name/tag so the pull fails; Docker daemon not running; private registry requiring credentials; container crashes immediately so the wait strategy times out; insufficient resources (OOM) killing the container during startup.
Related errors
- Could not create/start container
- Container did not start correctly.
- You should never close the global DockerClient!
- Check failed:
- Requested port ( ) is not mapped
AI-assisted analysis of testcontainers/testcontainers-java@8e549514e3 (2026-09-12).
Data as JSON: /api/errors/f9304ad06f20a882.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/testcontainers/containers/GenericContainer.java:346
logger().debug("Starting container: {}", getDockerImageName());
AtomicInteger attempt = new AtomicInteger(0);
Unreliables.retryUntilSuccess(
startupAttempts,
() -> {
logger()
.debug(
"Trying to start container: {} (attempt {}/{})",
getDockerImageName(),
attempt.incrementAndGet(),
startupAttempts
);
tryStart();
return true;
}
);
} catch (Exception e) {
throw new ContainerLaunchException("Container startup failed for image " + getDockerImageName(), e);
}
}
@UnstableAPI
@SneakyThrows
protected boolean canBeReused() {
for (Class<?> type = getClass(); type != GenericContainer.class; type = type.getSuperclass()) {
try {
Method method = type.getDeclaredMethod("containerIsCreated", String.class);
if (method.getDeclaringClass() != GenericContainer.class) {
logger().warn("{} can't be reused because it overrides {}", getClass(), method.getName());
return false;
}
} catch (NoSuchMethodException | NoClassDefFoundError e) {
// ignore
}
}
View on GitHub (pinned to 8e549514e3)