testcontainers/testcontainers-java · warning

: No exposed ports or mapped ports - cannot wait for status

Error message

{}: No exposed ports or mapped ports - cannot wait for status

What it means

HttpWaitStrategy.waitUntilReady() needs a port to issue its HTTP liveness request. When no liveness port was configured and the container exposes no ports (getLivenessCheckPorts() empty), it logs this warning and uses -1, which aborts the wait immediately, producing a ContainerLaunchException / wait failure instead of an HTTP check.

Solutions

  1. Expose the port the HTTP check should hit: container.addExposedPorts(8080) (or withExposedPorts in DockerComposeContainer rules).
  2. If the check must use a different port than the response port, set it explicitly with HttpWaitStrategy.forPort(8080).
  3. Ensure the image declares EXPOSE for the port so getLivenessCheckPorts() returns it.
  4. If using a custom WaitStrategyTarget, make getExposedPorts/getMappedPort return real values.

Example fix

// before
GenericContainer<?> c = new GenericContainer<>("myapp:latest")
    .waitingFor(Wait.forHttp("/health").forStatusCode(200)); // no ports exposed
// after
GenericContainer<?> c = new GenericContainer<>("myapp:latest")
    .withExposedPorts(8080)
    .waitingFor(Wait.forHttp("/health").forStatusCode(200).forPort(8080));
Defensive patterns

Strategy: validation

Validate before calling

if (container.getExposedPorts().isEmpty()) {
    throw new IllegalStateException("HttpWaitStrategy requires at least one exposed port; call addExposedPorts(...) first");
}

Try / catch

try {
    container.start();
} catch (ContainerLaunchException e) {
    if (e.getMessage().contains("No exposed ports")) { /* fix port exposure */ }
}

Prevention

When it happens

Trigger: Using HttpWaitStrategy (e.g. Wait.forHttp("/health")) on a container that calls neither .exposedPorts(...)/addExposedPort nor .withExposedPorts(...), and without HttpWaitStrategy.withLivenessPassingPorts()/livenessPort set — i.e. no exposed or mapped ports exist.

Common situations: Forgetting to call addExposedPorts() on GenericContainer while attaching an HTTP wait strategy; containers whose ports are declared only inside the image but the image has no EXPOSE; custom WaitStrategyTarget implementations not reporting ports.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


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

Appendix: source

Thrown at core/src/main/java/org/testcontainers/containers/wait/strategy/HttpWaitStrategy.java:217

     * Waits for the response to pass the given predicate
     * @param responsePredicate The predicate to test the response against
     * @return this
     */
    public HttpWaitStrategy forResponsePredicate(Predicate<String> responsePredicate) {
        this.responsePredicate = responsePredicate;
        return this;
    }

    @Override
    protected void waitUntilReady() {
        final String containerName = waitStrategyTarget.getContainerInfo().getName();

        final Integer livenessCheckPort = livenessPort
            .map(waitStrategyTarget::getMappedPort)
            .orElseGet(() -> {
                final Set<Integer> livenessCheckPorts = getLivenessCheckPorts();
                if (livenessCheckPorts == null || livenessCheckPorts.isEmpty()) {
                    log.warn("{}: No exposed ports or mapped ports - cannot wait for status", containerName);
                    return -1;
                }
                return livenessCheckPorts.iterator().next();
            });

        if (null == livenessCheckPort || -1 == livenessCheckPort) {
            return;
        }
        final URI rawUri = buildLivenessUri(livenessCheckPort);
        final String uri = rawUri.toString();

        try {
            // Un-map the port for logging
            int originalPort = waitStrategyTarget
                .getExposedPorts()
                .stream()
                .filter(exposedPort -> rawUri.getPort() == waitStrategyTarget.getMappedPort(exposedPort))
                .findFirst()

View on GitHub (pinned to 8e549514e3)