{"record":{"id":"7e2b6bd7359d1842","repo":"testcontainers/testcontainers-java","slug":"response-s-did-not-match-predicate","errorCode":null,"errorMessage":"Response: %s did not match predicate","messagePattern":"Response: (.+?) did not match predicate","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/testcontainers/containers/wait/strategy/HttpWaitStrategy.java","lineNumber":306,"sourceCode":"                                    predicate = statusCodePredicate;\n                                } else {\n                                    // We have both predicate and status code\n                                    predicate =\n                                        statusCodePredicate.or(responseCode -> statusCodes.contains(responseCode));\n                                }\n                                if (!predicate.test(connection.getResponseCode())) {\n                                    throw new RuntimeException(\n                                        String.format(\"HTTP response code was: %s\", connection.getResponseCode())\n                                    );\n                                }\n\n                                if (responsePredicate != null) {\n                                    String responseBody = getResponseBody(connection);\n\n                                    log.trace(\"Get response {}\", responseBody);\n\n                                    if (!responsePredicate.test(responseBody)) {\n                                        throw new RuntimeException(\n                                            String.format(\"Response: %s did not match predicate\", responseBody)\n                                        );\n                                    }\n                                }\n                            } catch (IOException e) {\n                                throw new RuntimeException(e);\n                            }\n                        });\n                    return true;\n                }\n            );\n        } catch (TimeoutException e) {\n            throw new ContainerLaunchException(\n                String.format(\n                    \"Timed out waiting for URL to be accessible (%s should return HTTP %s)\",\n                    uri,\n                    statusCodes.isEmpty() ? HttpURLConnection.HTTP_OK : statusCodes\n                ),","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/testcontainers/testcontainers-java/blob/8e549514e3f01c57d70546fbb8599d138f3903e5/core/src/main/java/org/testcontainers/containers/wait/strategy/HttpWaitStrategy.java#L288-L324","documentation":"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'.","triggerScenarios":"Calling HttpWaitStrategy.withResponsePredicate(body -> body.contains(\"OK\")) while the actual response body differs (empty body, JSON error payload, HTML error page).","commonSituations":"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.","solutions":["Log the actual body (it is printed in the message) and adjust the predicate to match reality","Parse structured bodies (e.g. with Jackson) instead of raw string matching","Make the predicate tolerant of intermediate states (e.g. accept both 'starting' and 'ready')","Combine with .forStatusCode(200) so obvious errors fail on status first"],"exampleFix":"// before\n.withResponsePredicate(body -> body.equals(\"OK\"))\n// after\n.withResponsePredicate(body -> body.contains(\"\\\"status\\\":\\\"UP\\\"\"))","handlingStrategy":"validation","validationCode":"// Assert the expected body shape against a live response before configuring the predicate\nString body = new HttpWaitStrategy().getResponseBody(\n    (HttpURLConnection) new URL(baseUrl + \"/health\").openConnection());\nif (!body.contains(\"\\\"status\\\":\\\"UP\\\"\")) {\n    throw new IllegalStateException(\"Unexpected body: \" + body);\n}","typeGuard":null,"tryCatchPattern":"try {\n    container.waitingFor(new HttpWaitStrategy().withResponsePredicate(this::isValidHealthBody)).start();\n} catch (ContainerLaunchException e) {\n    if (e.getMessage().contains(\"did not match predicate\")) {\n        // log real body from the message and refine the predicate\n    }\n    throw e;\n}","preventionTips":["Write predicates against parsed JSON, not raw string equality","Keep the predicate tolerant of intermediate app states","Version-check the app's health payload format when upgrading the app under test"],"tags":["http","wait-strategy","response-body","predicate","testcontainers"],"backgroundTag":"unexpected-response-shape","analyzedSha":"8e549514e3f01c57d70546fbb8599d138f3903e5","analyzedAt":"2026-09-12T14:56:41.227Z","contentChangedAt":"2026-09-12T14:56:41.227Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}