Testcontainers "Mapped port can only be obtained after the container is started" in CI
Testcontainers assigns a random host port only once the container is started, so calling getMappedPort before start() (or after the container stopped) throws. This is a lifecycle-ordering bug in the test, sometimes hidden locally but exposed by CI timing.
What this error means
The test fails with "Mapped port can only be obtained after the container is started" when building a connection URL, usually in setup code that runs before the container is actually started.
java.lang.IllegalStateException: Mapped port can only be obtained after the container is startedCommon causes
getMappedPort called before start()
Reading the mapped port during field initialization or before explicitly starting the container throws, because no host port exists yet.
Reading a port after the container stopped
If lifecycle management stops the container early (or a @Container field is misused), the port is no longer available.
How to fix it
Read the mapped port only after start
- Start the container (explicitly or via the JUnit lifecycle annotation).
- Build the connection URL after start, inside setup that runs post-start.
- Avoid reading the port during static field initialization.
container.start();
String url = "http://" + container.getHost() + ":" + container.getMappedPort(8080);Let the JUnit integration manage lifecycle
Use the Testcontainers JUnit annotations so the container is started before your test reads its port.
@Testcontainers
class MyTest {
@Container
static GenericContainer<?> app = new GenericContainer<>("myapp:latest").withExposedPorts(8080);
}How to prevent it
- Only query host and mapped port after the container has started.
- Prefer the JUnit lifecycle integration to order start before use.
- Keep connection-URL construction out of static initializers.