testcontainers/testcontainers-java · error · RuntimeException
HTTP response code was
Error message
HTTP response code was: %s
What it means
HttpWaitStrategy polls a container's HTTP endpoint until it is ready. This RuntimeException is thrown when the server responds but the status code fails the configured statusCodePredicate (e.g. you asked for HTTP 200 but got 404/500). It usually means the endpoint is reachable but not behaving as expected yet.
Solutions
- Verify the actual status code with curl against the mapped port and fix the expected path/port in the wait strategy
- Allow the observed status codes via .forStatusCode(...) or .forStatusCodeMatching(...)
- Ensure livenessPort/https settings match the container's real listening port and protocol
- Increase .withStartupTimeout(...) if the code only transitions to 200 after longer warm-up
Example fix
// before
new HttpWaitStrategy().forPort(8080).forPath("/health").forStatusCode(200);
// after
new HttpWaitStrategy().forPort(8080).forPath("/actuator/health").forStatusCode(200).forStatusCode(503).withStartupTimeout(Duration.ofSeconds(60)); Defensive patterns
Strategy: validation
Validate before calling
// Verify the endpoint before waiting
String url = "http://" + container.getHost() + ":" + container.getMappedPort(8080) + "/health";
HttpURLConnection c = (HttpURLConnection) new URL(url).openConnection();
int code = c.getResponseCode();
if (code != 200) throw new IllegalStateException("Endpoint returned " + code + ", adjust forStatusCode/forPath"); Try / catch
try {
container.waitingFor(new HttpWaitStrategy().forStatusCode(200)).start();
} catch (ContainerLaunchException e) {
if (e.getMessage().startsWith("HTTP response code was")) {
// inspect container logs / adjust status predicate
}
throw e;
} Prevention
- curl the mapped port and path before finalizing the wait strategy
- Allow every acceptable status code explicitly via forStatusCode/forStatusCodeMatching
- Keep wait path/port in sync with the application's real health endpoint
- Add generous withStartupTimeout for slow-warming apps
When it happens
Trigger: Calling HttpWaitStrategy.forStatusCode(200)/forStatusCodeMatching(predicate) (or default 200 requirement) while the container returns a different code, such as 404 for a wrong path or 503 while the app is still initializing.
Common situations: Wrong wait path/port configured; app returns 301/302 redirects instead of 200; endpoint returns 401 without auth headers; health endpoint briefly returns 503 during startup and the timeout window expires between polls.
Related errors
- Response: did not match predicate
- Timed out waiting for URL to be accessible
- you cannot specify a value smaller than 1 ms
- Unable to create custom SSL factory instance
- Timed out waiting for log output matching
AI-assisted analysis of testcontainers/testcontainers-java@8e549514e3 (2026-09-12).
Data as JSON: /api/errors/2f72155230babcc6.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/testcontainers/containers/wait/strategy/HttpWaitStrategy.java:295
// Choose the statusCodePredicate strategy depending on what we defined.
Predicate<Integer> predicate;
if (statusCodes.isEmpty() && statusCodePredicate == null) {
// We have no status code and no predicate so we expect a 200 OK response code
predicate = responseCode -> HttpURLConnection.HTTP_OK == responseCode;
} else if (!statusCodes.isEmpty() && statusCodePredicate == null) {
// We use the default status predicate checker when we only have status codes
predicate = responseCode -> statusCodes.contains(responseCode);
} else if (statusCodes.isEmpty()) {
// We only have a predicate
predicate = statusCodePredicate;
} else {
// We have both predicate and status code
predicate =
statusCodePredicate.or(responseCode -> statusCodes.contains(responseCode));
}
if (!predicate.test(connection.getResponseCode())) {
throw new RuntimeException(
String.format("HTTP response code was: %s", connection.getResponseCode())
);
}
if (responsePredicate != null) {
String responseBody = getResponseBody(connection);
log.trace("Get response {}", responseBody);
if (!responsePredicate.test(responseBody)) {
throw new RuntimeException(
String.format("Response: %s did not match predicate", responseBody)
);
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}View on GitHub (pinned to 8e549514e3)