elastic/elasticsearch · error · IllegalArgumentException

malformed version [${version}] for jdk [${name}]

Error message

malformed version [${version}] for jdk [${name}]

What it means

Thrown by Jdk.setVersion when the version string matches none of the three accepted patterns: VERSION_PATTERN (e.g. '17.0.1+12' or '21+34@abcdef...'), LEGACY_VERSION_PATTERN (pre-Java-9, e.g. '8u302+b08'), or EA_VERSION_PATTERN (early-access, e.g. '22-ea+15'). The version must be parseable so that major/base/build/hash components can be derived for constructing the download artifact path.

Source

Thrown at build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/Jdk.java:85

        return vendor.get();
    }

    public void setVendor(final String vendor) {
        if (ALLOWED_VENDORS.contains(vendor) == false) {
            throw new IllegalArgumentException("unknown vendor [" + vendor + "] for jdk [" + name + "], must be one of " + ALLOWED_VENDORS);
        }
        this.vendor.set(vendor);
    }

    public String getVersion() {
        return version.get();
    }

    public void setVersion(String version) {
        if (VERSION_PATTERN.matcher(version).matches() == false
            && LEGACY_VERSION_PATTERN.matcher(version).matches() == false
            && EA_VERSION_PATTERN.matcher(version).matches() == false) {
            throw new IllegalArgumentException("malformed version [" + version + "] for jdk [" + name + "]");
        }
        parseVersion(version);
        this.version.set(version);
    }

    public String getPlatform() {
        return platform.get();
    }

    public void setPlatform(String platform) {
        if (ALLOWED_PLATFORMS.contains(platform) == false) {
            throw new IllegalArgumentException(
                "unknown platform [" + platform + "] for jdk [" + name + "], must be one of " + ALLOWED_PLATFORMS
            );
        }
        this.platform.set(platform);
    }

View on GitHub (pinned to db6a809a66)

Solutions

  1. Use the JEP-322 format with a build suffix: '<feature>[.<interim>.<update>[.<patch>]]+<build>[@<32-hex-sha>]', e.g. '21.0.3+9'.
  2. For JDK 8 use the legacy form '<major>u<update>+b<build>[@hash]', e.g. '8u402+b06'.
  3. For early-access builds use '<major>-ea+<build>' or '<major>-rc+<build>'.
  4. Copy the exact version string (including build and, when present, the @hash) from the build's VersionProperties or the JDK download page.

Example fix

// before
jdks { build_jdk { version = '17.0.1'; } }  // missing build number
// after
jdks { build_jdk { version = '17.0.1+12'; } }
Defensive patterns

Strategy: validation

Validate before calling

import java.util.regex.Pattern;
private static final Pattern VERSION = Pattern.compile(
    "(\\d+)(\\.\\d+\\.\\d+(\\.\\d+)?)?\\+(\\d+(\\.\\d+)?)(@([a-f0-9]{32}))?");
private static final Pattern LEGACY = Pattern.compile("(\\d)(u\\d+)\\+(b\\d+?)(@([a-f0-9]{32}))?");
private static final Pattern EA = Pattern.compile("(\\d+)-(?:ea|rc)\\+(\\d+)(@([a-f0-9]{32}))?");
boolean isValidJdkVersion(String v) {
    return VERSION.matcher(v).matches() || LEGACY.matcher(v).matches() || EA.matcher(v).matches();
}
// assert isValidJdkVersion("21.0.3+9");
// assert isValidJdkVersion("8u402+b06");
// assert isValidJdkVersion("23-ea+15");

Prevention

When it happens

Trigger: Jdk.setVersion(version) is called with a string that fails all three regex matches. The patterns require a build number component (the '+N' suffix) and an optional '@<32-hex-hash>' suffix; bare version numbers like '17' or Maven-style '17.0.1' without a build are rejected.

Common situations: Omitting the mandatory build number (e.g. '17.0.1' instead of '17.0.1+12'); using a Maven/Gradle dependency version like '17.0.1-12'; supplying only a major ('21'); including a patch segment the parser doesn't model; copy-pasting a version from a vendor page that uses a different separator.

Understand the failure class

Related errors


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