testcontainers/testcontainers-java · error · java.lang.IllegalStateException
Failed to verify that image
Error message
Failed to verify that image '%s' is a compatible substitute for '%s'. This generally means that you are trying to use an image that Testcontainers has not been designed to use. If this is deliberate, and if you are confident that the image is compatible, you should declare compatibility in code using the `asCompatibleSubstituteFor` method. For example:
DockerImageName myImage = DockerImageName.parse("%s").asCompatibleSubstituteFor("%s");
and then use `myImage` instead. What it means
assertCompatibleWith verifies that the image being used is compatible with an image Testcontainers was designed for (same repository, or declared via asCompatibleSubstituteFor). If no candidate matches, it throws IllegalStateException with a long explanation and a code example showing how to declare compatibility. This prevents silently running an incompatible drop-in image against container-specific logic.
Solutions
- If the image truly is a compatible substitute, declare it: DockerImageName.parse("myimage").asCompatibleSubstituteFor("postgres") and pass the result to the container.
- If using a registry mirror, check the container module's mirror-configuration support (e.g. TestcontainersConfiguration or the module's image constant) so the expected repo is matched against your mirror.
- If the image genuinely differs, use the correct Testcontainers module or a GenericContainer instead of forcing substitution.
Example fix
// before
new PostgreSQLContainer(DockerImageName.parse("registry.mycorp.io/pg-mirror:16"));
// after
new PostgreSQLContainer(
DockerImageName.parse("registry.mycorp.io/pg-mirror:16").asCompatibleSubstituteFor("postgres")); Defensive patterns
Strategy: try-catch
Validate before calling
DockerImageName parsed = DockerImageName.parse(raw);
if (!parsed.isCompatibleWith(DockerImageName.parse("postgres"))) {
parsed = parsed.asCompatibleSubstituteFor("postgres");
} Try / catch
try {
container.start();
} catch (IllegalStateException e) {
if (e.getMessage().startsWith("Failed to verify that image")) {
log.error("Incompatible substitute image; declare via asCompatibleSubstituteFor");
}
throw e;
} Prevention
- Always wrap registry-mirror images with asCompatibleSubstituteFor
- Use isCompatibleWith in tests to assert image choices
- Keep mirror names in config rather than changing repository paths
When it happens
Trigger: Starting a container module with a substitute image whose repository differs from the expected one without calling asCompatibleSubstituteFor, e.g. new PostgreSQLContainer(DockerImageName.parse("myregistry/postgres-mirror:16")) — a mirror with a non-matching repo name.
Common situations: Using private registry mirrors or proxies whose full name doesn't end with the expected repo (e.g. 'docker.mycorp.io/postgres' parses differently than expected); using lookalike images (mysql for mariadb and vice versa); vendor forks named differently.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- This container's image does not have a healthcheck…
- is not a valid Docker image name (in )
- is not a valid image versioning identifier (in )
- anyOthers parameter must be non-empty
- Kibana version is not supported. Minimum version is
AI-assisted analysis of testcontainers/testcontainers-java@8e549514e3 (2026-09-12).
Data as JSON: /api/errors/7d7fd0569a70e891.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/testcontainers/utility/DockerImageName.java:309
* than one is provided, this method will check compatibility with at least one
* of them.
* @throws IllegalStateException if {@link DockerImageName#isCompatibleWith(DockerImageName)}
* returns false
*/
public void assertCompatibleWith(DockerImageName... anyOthers) {
if (anyOthers.length == 0) {
throw new IllegalArgumentException("anyOthers parameter must be non-empty");
}
for (DockerImageName anyOther : anyOthers) {
if (this.isCompatibleWith(anyOther)) {
return;
}
}
final DockerImageName exampleOther = anyOthers[0];
throw new IllegalStateException(
String.format(
"Failed to verify that image '%s' is a compatible substitute for '%s'. This generally means that " +
"you are trying to use an image that Testcontainers has not been designed to use. If this is " +
"deliberate, and if you are confident that the image is compatible, you should declare " +
"compatibility in code using the `asCompatibleSubstituteFor` method. For example:\n" +
" DockerImageName myImage = DockerImageName.parse(\"%s\").asCompatibleSubstituteFor(\"%s\");\n" +
"and then use `myImage` instead.",
this.rawName,
exampleOther.rawName,
this.rawName,
exampleOther.rawName
)
);
}
}
View on GitHub (pinned to 8e549514e3)