elastic/elasticsearch · error · IllegalStateException

No read-only compatible version found.

Error message

No read-only compatible version found.

What it means

Thrown by BwcVersions.withLatestReadOnlyIndexCompatible when getReadOnlyIndexCompatible() returns null or an empty list. Lucene can read indices from N-2 majors; this fires when no version two majors below the current one is registered in the parsed version set.

Source

Thrown at build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/BwcVersions.java:216

    }

    public List<Version> getReleased() {
        return versions.stream()
            .filter(v -> v.getMajor() >= currentVersion.getMajor() - 1)
            .filter(v -> unreleased.containsKey(v) == false)
            .toList();
    }

    public List<Version> getReadOnlyIndexCompatible() {
        // Lucene can read indices in version N-2
        int compatibleMajor = currentVersion.getMajor() - 2;
        return versions.stream().filter(v -> v.getMajor() == compatibleMajor).sorted(Comparator.naturalOrder()).toList();
    }

    public void withLatestReadOnlyIndexCompatible(Consumer<Version> versionAction) {
        var compatibleVersions = getReadOnlyIndexCompatible();
        if (compatibleVersions == null || compatibleVersions.isEmpty()) {
            throw new IllegalStateException("No read-only compatible version found.");
        }
        versionAction.accept(compatibleVersions.getLast());
    }

    /**
     * Return versions of Elasticsearch which are index compatible with the current version.
     */
    public List<Version> getIndexCompatible() {
        return versions.stream().filter(v -> v.getMajor() >= (currentVersion.getMajor() - 1)).toList();
    }

    public void withIndexCompatible(BiConsumer<Version, String> versionAction) {
        getIndexCompatible().forEach(v -> versionAction.accept(v, "v" + v.toString()));
    }

    public void withIndexCompatible(Predicate<Version> filter, BiConsumer<Version, String> versionAction) {
        getIndexCompatible().stream().filter(filter).forEach(v -> versionAction.accept(v, "v" + v.toString()));
    }

View on GitHub (pinned to db6a809a66)

Solutions

  1. Ensure N-2 major versions are present in Version.java so the read-only-compatible set is non-empty.
  2. Verify version parsing returned the full historical list (see error 130 causes).
  3. Confirm the current major is correctly configured in build properties.
Defensive patterns

Strategy: validation

Validate before calling

List<Version> compatible = getReadOnlyIndexCompatible();
if (compatible == null || compatible.isEmpty()) {
    throw new IllegalStateException("No read-only compatible version found.");
}

Prevention

When it happens

Trigger: The current major is so new (or the version list is so truncated) that no N-2 major version exists in the parsed list, so getReadOnlyIndexCompatible filters down to nothing.

Common situations: Very early in a new major cycle before N-2 versions are populated; version parsing returned a partial list; corrupt or truncated Version.java.

Related errors


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