testcontainers/testcontainers-java · warning
Version is not a semantic version, LocalStack will run in…
Error message
Version {} is not a semantic version, LocalStack will run in legacy mode. What it means
shouldRunInLegacyMode compares the LocalStack image version to 0.11 to decide between the legacy single-container setup and the modern one. When the version tag is not a semantic version, the method logs this warning (plus the follow-up constructor hint) and returns true, forcing legacy mode. Users with non-standard image tags get legacy behavior they may not expect.
Solutions
- Pin a semantic version tag such as localstack/localstack:2.3.0
- Use the explicit constructor new LocalStackContainer(image, false) to opt out of legacy mode regardless of tag parsing
- Set up withServices() explicitly so the container config is intentional
Example fix
// before
new LocalStackContainer(DockerImageName.parse("localstack/localstack:nightly"))
// after
new LocalStackContainer(DockerImageName.parse("localstack/localstack:2.3.0"), false) Defensive patterns
Strategy: validation
Validate before calling
String tag = imageName.getVersionPart();
if (!tag.matches("\\d+(\\.\\d+)*")) {
// choose mode explicitly rather than letting the fallback decide
}
new LocalStackContainer(imageName, /*legacyMode*/ false); Prevention
- Use the (DockerImageName, boolean legacyMode) constructor when tags are not semver
- Pin localstack to semver tags in CI
- Assert expected container config (env vars) in an integration smoke test
When it happens
Trigger: Creating LocalStackContainer with an image tag that cannot be parsed as a semantic version (e.g. :latest, :nightly, custom tags); the static shouldRunInLegacyMode(version) check falls into the non-semantic branch.
Common situations: CI caching 'latest' of localstack; local builds tagged 'local'; older testcontainers code paths that accepted arbitrary image names.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Version is not a semantic version, services list is…
- Consider using "LocalStackContainer(DockerImageName…
- No explicit version tag was provided in JDBC URL and this…
- Version is not a semantic version. The function…
- Copying databases is only supported for Neo4j versions 3.5.x
AI-assisted analysis of testcontainers/testcontainers-java@8e549514e3 (2026-09-12).
Data as JSON: /api/errors/0de177dd9dfdcae2.
Report an issue: GitHub.
Appendix: source
Thrown at modules/localstack/src/main/java/org/testcontainers/containers/localstack/LocalStackContainer.java:175
log.warn("Version {} is not a semantic version, services list is required.", version);
return true;
}
static boolean shouldRunInLegacyMode(String version) {
// assume that the latest images are up-to-date
// also consider images with extra packages (like latest-bigdata) and service-specific images (like s3-latest)
if (version.equals("latest") || version.startsWith("latest-") || version.endsWith("-latest")) {
return false;
}
ComparableVersion comparableVersion = new ComparableVersion(version);
if (comparableVersion.isSemanticVersion()) {
boolean versionRequiresLegacyMode = comparableVersion.isLessThan("0.11");
return versionRequiresLegacyMode;
}
log.warn("Version {} is not a semantic version, LocalStack will run in legacy mode.", version);
log.warn(
"Consider using \"LocalStackContainer(DockerImageName dockerImageName, boolean legacyMode)\" constructor if you want to disable legacy mode."
);
return true;
}
@Override
protected void configure() {
super.configure();
if (this.servicesEnvVarRequired) {
Preconditions.check("services list must not be empty", !services.isEmpty());
}
if (!services.isEmpty()) {
withEnv("SERVICES", services.stream().map(EnabledService::getName).collect(Collectors.joining(",")));
if (this.servicesEnvVarRequired) {
withEnv("EAGER_SERVICE_LOADING", "1");View on GitHub (pinned to 8e549514e3)