oracle/graal · error · IllegalArgumentException

Boolean option '%s' must have value "true" or "false", not "

Error message

Boolean option '%s' must have value "true" or "false", not "%s"

What it means

Thrown by OptionsParser.parseOptionValue when a Boolean-typed option receives a String value that is neither exactly 'true' nor 'false'. The parser is deliberately strict: no 'yes'/'no', '1'/'0', or mixed-case variants are accepted, because these flags map directly to -Dgraal.<Name>=<value> JVM properties.

Source

Thrown at compiler/src/jdk.graal.compiler.options/src/jdk/graal/compiler/options/OptionsParser.java:238

     * Parses a given option value with a known descriptor.
     */
    public static Object parseOptionValue(OptionDescriptor desc, Object uncheckedValue) {
        Class<?> optionType = desc.getOptionValueType();
        Object value;
        if (!(uncheckedValue instanceof String valueString)) {
            if (optionType != uncheckedValue.getClass()) {
                String type = optionType.getSimpleName();
                throw new IllegalArgumentException(type + " option '" + desc.getName() + "' must have " + type + " value, not " + uncheckedValue.getClass() + " [toString: " + uncheckedValue + "]");
            }
            value = uncheckedValue;
        } else {
            if (optionType == Boolean.class) {
                if ("true".equals(valueString)) {
                    value = Boolean.TRUE;
                } else if ("false".equals(valueString)) {
                    value = Boolean.FALSE;
                } else {
                    throw new IllegalArgumentException("Boolean option '" + desc.getName() + "' must have value \"true\" or \"false\", not \"" + uncheckedValue + "\"");
                }
            } else if (optionType == String.class) {
                value = valueString;
            } else if (Enum.class.isAssignableFrom(optionType)) {
                value = ((EnumOptionKey<?>) desc.getOptionKey()).valueOf(valueString);
            } else if (optionType == EconomicSet.class) {
                value = ((EnumMultiOptionKey<?>) desc.getOptionKey()).valueOf(valueString);
            } else {
                if (valueString.isEmpty()) {
                    throw new IllegalArgumentException("Non empty value required for option '" + desc.getName() + "'");
                }
                try {
                    if (optionType == Float.class) {
                        value = Float.parseFloat(valueString);
                    } else if (optionType == Double.class) {
                        value = Double.parseDouble(valueString);
                    } else if (optionType == Integer.class) {
                        value = (int) parseLong(valueString);

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Use exactly true or false, lowercase, with no surrounding whitespace.
  2. Normalize before passing: value.trim().toLowerCase(Locale.ROOT), and map 1/0/yes/no to true/false in your own config layer.
  3. If the value comes from an env var, document that only 'true'/'false' are accepted or convert it at the boundary.

Example fix

// before
OptionsParser.parseOptionSettingTo("PrintGraph=True", values);

// after
OptionsParser.parseOptionSettingTo("PrintGraph=true", values);
Defensive patterns

Strategy: validation

Validate before calling

String normalizeBoolean(String raw) {
    String v = raw.trim().toLowerCase(Locale.ROOT);
    switch (v) {
        case "true": case "yes": case "1": return "true";
        case "false": case "no": case "0": return "false";
        default: throw new IllegalArgumentException("Not a boolean: " + raw);
    }
}

OptionsParser.parseOptionSettingTo(name + "=" + normalizeBoolean(rawValue), dst);

Type guard

boolean isGraalBooleanLiteral(String s) {
    return "true".equals(s) || "false".equals(s);
}

Try / catch

try {
    OptionsParser.parseOptionSettingTo(setting, dst);
} catch (IllegalArgumentException e) {
    if (e.getMessage().startsWith("Boolean option")) {
        throw new ConfigException("Option value '" + setting + "' must be exactly true or false (lowercase)", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Passing 'True', 'TRUE', '1', 'yes', or '' as the string value of a Boolean option, e.g. parseOptions("PrintGraph=Yes", ...) or -Dgraal.PrintGraph=1. Only exact lowercase "true"/"false" match.

Common situations: Shell scripts upper-casing values (${FLAG^^}); YAML/JSON config with boolean true serialized as 'True' or 'yes'; environment variables defaulting to '1'; locale-specific or whitespace-padded values ('true ') failing the equals check.

Related errors


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