elastic/elasticsearch · error · IllegalArgumentException

Release [%s] already recorded with version id [%s], cannot u

Error message

Release [%s] already recorded with version id [%s], cannot update to version [%s]

What it means

Thrown in TagVersionsTask.addVersionRecord() when the release version is already present in the record file but with a DIFFERENT id than the one being written. An identical id is a no-op (returns Optional.empty() with a lifecycle log); a conflicting id is rejected to keep the version→id mapping authoritative.

Source

Thrown at build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/TagVersionsTask.java:115

        return Map.of(INDEX_VERSION_TYPE, v7Version);
    }

    private static final Pattern VERSION_LINE = Pattern.compile("(\\d+\\.\\d+\\.\\d+),(\\d+)");

    static Optional<List<String>> addVersionRecord(List<String> versionRecordLines, Version release, int id) {
        Map<Version, Integer> versions = versionRecordLines.stream().map(l -> {
            Matcher m = VERSION_LINE.matcher(l);
            if (m.matches() == false) throw new IllegalArgumentException(String.format("Incorrect format for line [%s]", l));
            return m;
        }).collect(Collectors.toMap(m -> Version.fromString(m.group(1)), m -> Integer.parseInt(m.group(2))));

        Integer existing = versions.putIfAbsent(release, id);
        if (existing != null) {
            if (existing.equals(id)) {
                LOGGER.lifecycle("Version id [{}] for release [{}] already recorded", id, release);
                return Optional.empty();
            } else {
                throw new IllegalArgumentException(
                    String.format(
                        "Release [%s] already recorded with version id [%s], cannot update to version [%s]",
                        release,
                        existing,
                        id
                    )
                );
            }
        }

        return Optional.of(
            versions.entrySet().stream().sorted(Map.Entry.comparingByKey()).map(e -> e.getKey() + "," + e.getValue()).toList()
        );
    }
}

View on GitHub (pinned to db6a809a66)

Solutions

  1. Confirm the intended id matches the one already recorded for that release; if so, no action is needed (it is idempotent).
  2. If the id genuinely must change, manually correct the record file under supervision and re-run, recording the change in the release audit log.
  3. Prevent re-running tagVersions for an already-released version in the release automation.
Defensive patterns

Strategy: validation

Validate before calling

// Check whether the release is already recorded before tagging
static boolean alreadyRecorded(Path recordFile, Version release) throws IOException {
    return Files.readAllLines(recordFile).stream()
        .map(l -> l.split(","))
        .anyMatch(p -> Version.fromString(p[0]).equals(release));
}
// skip tagging if alreadyRecorded(...) returns true

Prevention

When it happens

Trigger: Re-running tagVersions for an already-released version with a new --tag-version id, e.g. the release was first tagged Index:42 and is now being tagged Index:43.

Common situations: A release engineer mistakenly re-tags; the id space was renumbered; the same version is being processed by two concurrent release runs.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/de197a0c09d3ae6a. Report an issue: GitHub.