testcontainers/testcontainers-java · error · RuntimeException

Response: did not match predicate

Error message

Response: %s did not match predicate

What it means

HttpWaitStrategy supports an optional body-level predicate set with withResponsePredicate. When the HTTP status passes but the response body fails that predicate, this RuntimeException is thrown so the strategy keeps retrying until timeout. It means the endpoint answered correctly at the HTTP level but its content is not what you declared as 'ready'.

Solutions

  1. Log the actual body (it is printed in the message) and adjust the predicate to match reality
  2. Parse structured bodies (e.g. with Jackson) instead of raw string matching
  3. Make the predicate tolerant of intermediate states (e.g. accept both 'starting' and 'ready')
  4. Combine with .forStatusCode(200) so obvious errors fail on status first

Example fix

// before
.withResponsePredicate(body -> body.equals("OK"))
// after
.withResponsePredicate(body -> body.contains("\"status\":\"UP\""))
Defensive patterns

Strategy: validation

Validate before calling

// Assert the expected body shape against a live response before configuring the predicate
String body = new HttpWaitStrategy().getResponseBody(
    (HttpURLConnection) new URL(baseUrl + "/health").openConnection());
if (!body.contains("\"status\":\"UP\"")) {
    throw new IllegalStateException("Unexpected body: " + body);
}

Try / catch

try {
    container.waitingFor(new HttpWaitStrategy().withResponsePredicate(this::isValidHealthBody)).start();
} catch (ContainerLaunchException e) {
    if (e.getMessage().contains("did not match predicate")) {
        // log real body from the message and refine the predicate
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling HttpWaitStrategy.withResponsePredicate(body -> body.contains("OK")) while the actual response body differs (empty body, JSON error payload, HTML error page).

Common situations: Predicate written against a response format that changed between app versions; JSON body compared with plain-string contains instead of parsing; charset/encoding mismatch making the body look different.

Related errors


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

Appendix: source

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

                                    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);
                            }
                        });
                    return true;
                }
            );
        } catch (TimeoutException e) {
            throw new ContainerLaunchException(
                String.format(
                    "Timed out waiting for URL to be accessible (%s should return HTTP %s)",
                    uri,
                    statusCodes.isEmpty() ? HttpURLConnection.HTTP_OK : statusCodes
                ),

View on GitHub (pinned to 8e549514e3)