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
- Use exactly true or false, lowercase, with no surrounding whitespace.
- Normalize before passing: value.trim().toLowerCase(Locale.ROOT), and map 1/0/yes/no to true/false in your own config layer.
- 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
- Lowercase and trim boolean values at your config boundary before building -Dgraal flags.
- Map 1/0/yes/no to true/false yourself; Graal accepts only the exact literals.
- Add unit tests asserting emitted flag strings for boolean options.
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
- Non empty value required for option '%s'
- Value for option '${desc.getName()}' has invalid number form
- OnShutdownCallback value does not have <classname>.<method n
- Invalid replay boolean flag
- Required replay field is null
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/c5bc66943f4ef12e.
Report an issue: GitHub.