oracle/graal · error · IllegalArgumentException

Unsupported java version: {} ({})

Error message

Unsupported java version: {} ({})

What it means

JavaVersion.forVersion(String) strips an optional '1.' prefix (1.8 -> 8) and takes everything up to the next dot, then Integer.parseInt. If that normalized substring is not an integer, NumberFormatException is wrapped in IllegalArgumentException showing both the original and normalized version.

Source

Thrown at espresso-shared/src/com.oracle.truffle.espresso.classfile/src/com/oracle/truffle/espresso/classfile/JavaVersion.java:110

        return new JavaVersion(version);
    }

    public static JavaVersion forVersion(String version) {
        int begin = 0;
        int end = version.length();
        if (version.startsWith("1.")) {
            begin = 2;
        }
        int firstDot = version.indexOf('.', begin);
        if (firstDot >= 0) {
            end = firstDot;
        }
        String normalizedVersion = version.substring(begin, end);
        try {
            int intVersion = Integer.parseInt(normalizedVersion);
            return forVersion(intVersion);
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("Unsupported java version: " + version + " (" + normalizedVersion + ")");
        }
    }

    public Runtime.Version toRunTimeVersion() {
        return Runtime.Version.parse(toString());
    }

    private static JavaVersion forVersion(Runtime.Version version) {
        return forVersion(version.feature());
    }

    public static JavaVersion latestSupported() {
        return forVersion(LATEST_SUPPORTED);
    }

    public boolean java8OrEarlier() {
        return version <= 8;
    }

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Normalize first: strip prefixes/suffixes and keep only the leading digit run (e.g. regex ^(1\.)?(\d+)) before calling forVersion
  2. For runtime use Runtime.Version.parse(...).feature() and the Runtime.Version overload instead of hand-parsing strings
  3. Reject empty/blank input early with a clear configuration error

Example fix

// before
JavaVersion v = JavaVersion.forVersion("17-ea"); // NumberFormatException on '17-ea'

// after
Matcher m = Pattern.compile("^(?:1\.)?(\d+)").matcher(version);
JavaVersion v = m.find() ? JavaVersion.forVersion(Integer.parseInt(m.group(1))) : JavaVersion.latestSupported();
Defensive patterns

Strategy: validation

Validate before calling

Matcher m = Pattern.compile("^(?:1\.)?(\d+)").matcher(version);
if (!m.find()) throw new IllegalArgumentException("Unparseable version: " + version);
JavaVersion.forVersion(Integer.parseInt(m.group(1)));

Type guard

static boolean isParsableVersion(String s) { return s != null && Pattern.compile("^(?:1\.)?\d+").matcher(s).find(); }

Try / catch

catch (IllegalArgumentException e) { show original and normalized strings, reject the config input }

Prevention

When it happens

Trigger: Passing strings like 'abc', '1.x', 'v17', '17-pre2', '8u40', or '' (empty) — any version string whose leading dot-free segment is not purely digits.

Common situations: Feeding System.getProperty('java.version') raw values from old JDKs ('1.8.0_282' works, but '8u40' or '17-ea' do not), user-supplied --release style flags, or build metadata accidentally concatenated to the version string.

Related errors


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/ba40912912bc309a. Report an issue: GitHub.