elastic/elasticsearch · error · IllegalArgumentException
Invalid version format: '{}'. Should be {}
Error message
Invalid version format: '{}'. Should be {} What it means
Version.fromString() throws IllegalArgumentException when the input does not match the parsing regex. In STRICT mode (default), the pattern is (\d+)\.(\d+)\.(\d+)(?:-(alpha\d+|beta\d+|rc\d+|SNAPSHOT))? — i.e., major.minor.revision with an optional qualifier of alpha<N>, beta<N>, rc<N>, or SNAPSHOT. In RELAXED mode, a broader pattern allows an optional v prefix, optional revision, and arbitrary alphanumeric suffixes.
Source
Thrown at build-tools/src/main/java/org/elasticsearch/gradle/Version.java:74
// currently qualifier is not taken into account
this.id = major * 10000000 + minor * 100000 + revision * 1000;
this.qualifier = qualifier;
}
public static Version fromString(final String s) {
return fromString(s, Mode.STRICT);
}
public static Version fromString(final String s, final Mode mode) {
Objects.requireNonNull(s);
Matcher matcher = mode == Mode.STRICT ? pattern.matcher(s) : relaxedPattern.matcher(s);
if (matcher.matches() == false) {
String expected = mode == Mode.STRICT
? "major.minor.revision[-(alpha|beta|rc)Number|-SNAPSHOT]"
: "major.minor.revision[-extra]";
throw new IllegalArgumentException("Invalid version format: '" + s + "'. Should be " + expected);
}
String major = matcher.group(1);
String minor = matcher.group(2);
String revision = matcher.group(3);
String qualifier = matcher.group(4);
return new Version(Integer.parseInt(major), Integer.parseInt(minor), revision == null ? 0 : Integer.parseInt(revision), qualifier);
}
@Override
public String toString() {
return getMajor() + "." + getMinor() + "." + getRevision();
}
public boolean before(Version compareTo) {
return id < compareTo.getId();
}View on GitHub (pinned to db6a809a66)
Solutions
- Reformat the version to major.minor.revision with an optional -(alpha|beta|rc)N or -SNAPSHOT suffix for STRICT parsing.
- If the string uses a broader format (v prefix, custom suffix), parse with Version.fromString(s, Mode.RELAXED).
- Strip build metadata (+...) and any non-conforming qualifier before parsing.
- Validate with a regex pre-check if version strings come from external/untrusted sources.
Example fix
// before
Version v = Version.fromString("1.2.3-stable"); // throws in STRICT
// after (option 1: conform)
Version v = Version.fromString("1.2.3");
// after (option 2: relaxed)
Version v = Version.fromString("1.2.3-stable", Version.Mode.RELAXED); Defensive patterns
Strategy: validation
Validate before calling
private static final Pattern STRICT = Pattern.compile("(\\d+)\\.(\\d+)\\.(\\d+)(?:-(alpha\\d+|beta\\d+|rc\\d+|SNAPSHOT))?");
if (!STRICT.matcher(version).matches() && !RELAXED.matcher(version).matches()) {
throw new IllegalArgumentException("Version '" + version + "' matches neither strict nor relaxed format");
}
Version.fromString(version, STRICT.matcher(version).matches() ? Version.Mode.STRICT : Version.Mode.RELAXED); Type guard
static boolean isParsableVersion(String s) {
return Pattern.compile("(\\\\d+)\\\\.(\\\\d+)\\\\.(\\\\d+)(?:-(alpha\\\\d+|beta\\\\d+|rc\\\\d+|SNAPSHOT))?").matcher(s).matches();
} Try / catch
try { Version v = Version.fromString(s); } catch (IllegalArgumentException e) { /* try relaxed, or sanitize the string */ Version v = Version.fromString(s, Version.Mode.RELAXED); } Prevention
- Conform to major.minor.revision with optional -(alpha|beta|rc)N or -SNAPSHOT for STRICT parsing.
- Use Mode.RELAXED for v-prefixed tags or custom suffixes.
- Strip build metadata (+...) before parsing.
- Validate external version strings with a regex before passing to fromString.
When it happens
Trigger: Calling Version.fromString(s) (STRICT) or Version.fromString(s, Mode.RELAXED) with a non-conforming string. STRICT rejects: missing revision (1.2), spaces, unknown qualifiers (1.2.3-stable, 1.2.3.rc1), extra components (1.2.3.4), build metadata (1.2.3+build5).
Common situations: Parsing a dependency version string that uses a non-Elasticsearch format (SemVer build metadata, CalVer, custom suffixes like -dev, -RELEASE); passing a Git tag like v1.2.3 in STRICT mode (the v prefix is only allowed in RELAXED); a null or empty string (null throws NPE earlier via Objects.requireNonNull); typos in version config.
Related errors
- Elasticsearch version is missing from properties.
- Expected elasticsearch version to be numbers only of the for
- Invalid qualifier: ${qualifier}
- build.snapshot was set to [${buildSnapshotSystemProperty}] b
- License category name must be exactly 5 characters, got ${ca
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/69cf297e3b8efe00.
Report an issue: GitHub.