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
- Expose the port the HTTP check should hit: container.addExposedPorts(8080) (or withExposedPorts in DockerComposeContainer rules).
- If the check must use a different port than the response port, set it explicitly with HttpWaitStrategy.forPort(8080).
- Ensure the image declares EXPOSE for the port so getLivenessCheckPorts() returns it.
- 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
- Always call withExposedPorts/addExposedPorts before attaching HTTP wait strategies.
- Ensure the image has EXPOSE directives.
- Specify .forPort(...) explicitly on HttpWaitStrategy.
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
- Services named do not exist, but wait conditions have been…
- you cannot specify a value smaller than 1 ms
- HTTP response code was
- Response: did not match predicate
- Timed out waiting for URL to be accessible
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)