elastic/elasticsearch · error · IllegalArgumentException
Duplicate version constants {v1}
Error message
Duplicate version constants {v1} What it means
Thrown inside the Collectors.toMap merge function in UpdateVersionsTask while scanning Version.java field declarations: two distinct fields both parsed to the same Version value. This indicates a real duplication defect in the Version constants source file.
Source
Thrown at build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/UpdateVersionsTask.java:139
}
}
@VisibleForTesting
static Optional<CompilationUnit> addVersionConstant(CompilationUnit versionJava, Version version, boolean updateCurrent) {
String newFieldName = toVersionField(version);
ClassOrInterfaceDeclaration versionClass = versionJava.getClassByName("Version").get();
if (versionClass.getFieldByName(newFieldName).isPresent()) {
LOGGER.lifecycle("New version constant [{}] already present, skipping", newFieldName);
return Optional.empty();
}
NavigableMap<Version, FieldDeclaration> versions = versionClass.getFields()
.stream()
.map(f -> Map.entry(f, parseVersionField(f.getVariable(0).getNameAsString())))
.filter(e -> e.getValue().isPresent())
.collect(Collectors.toMap(e -> e.getValue().get(), Map.Entry::getKey, (v1, v2) -> {
throw new IllegalArgumentException("Duplicate version constants " + v1);
}, TreeMap::new));
// find the version this should be inserted after
var previousVersion = versions.lowerEntry(version);
if (previousVersion == null) {
throw new IllegalStateException(String.format("Could not find previous version to [%s]", version));
}
FieldDeclaration newVersion = createNewVersionConstant(
previousVersion.getValue(),
newFieldName,
String.format("%d_%02d_%02d_99", version.getMajor(), version.getMinor(), version.getRevision())
);
versionClass.getMembers().addAfter(newVersion, previousVersion.getValue());
if (updateCurrent) {
versionClass.getFieldByName("CURRENT")
.orElseThrow(() -> new IllegalArgumentException("Could not find CURRENT constant"))
.getVariable(0)View on GitHub (pinned to db6a809a66)
Solutions
- Open server/.../Version.java and find the two constants whose parsed version collides; remove or rename the erroneous one.
- Run parseVersionField logic mentally on each field name to spot the collision.
- Re-run updateVersions after fixing the source file.
Defensive patterns
Strategy: validation
Validate before calling
// Scan Version.java for duplicate parsed versions before running the task
Pattern VF = Pattern.compile("V_(\\d+)_(\\d+)_(\\d+)_(\\d+)");
Map<String, Long> counts = Files.readAllLines(versionJava)
.stream().map(VF::matcher).filter(Matcher::find)
.map(m -> m.group(1)+"."+m.group(2)+"."+m.group(3)+"("+m.group(4)+")")
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
Map<String,Long> dups = counts.entrySet().stream().filter(e -> e.getValue() > 1)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
if (!dups.isEmpty()) throw new IllegalStateException("Duplicate version constants: " + dups); Prevention
- When renaming a version constant, delete the old field in the same commit.
- Add a CI check that asserts each parsed version in Version.java is unique.
When it happens
Trigger: Version.java contains two field constants whose names parse via VERSION_FIELD to the same (major, minor, revision, qualifier). A merge in toMap then hits the collision merger.
Common situations: A botched merge introduced a duplicate version constant; a constant was renamed but the old one was not removed; the naming convention (V_X_YY_ZZ) collided for two qualifiers.
Related errors
- Cannot remove version [%s], it is referenced by CURRENT
- Incorrect format for line [%s]
- Release [%s] already recorded with version id [%s], cannot u
- Branch {branch} already exists
- Failed to read branches.json from {path}
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/4704421bdfc877b2.
Report an issue: GitHub.