oracle/graal · error · IllegalArgumentException
Invalid log level %s specified. %s'
Error message
Invalid log level %s specified. %s'
What it means
Thrown by EspressoExternalVMAccessBuilder while parsing a 'log.<name>.level' VM option (e.g. -Djava.log.espresso.level=...). The value must be parseable by java.util.logging.Level.parse; anything else is rejected with IllegalArgumentException before the option reaches the engine.
Source
Thrown at espresso-compiler-stub/src/com.oracle.truffle.espresso.vmaccess/src/com/oracle/truffle/espresso/vmaccess/EspressoExternalVMAccessBuilder.java:199
key = vmOption.substring(0, eqIdx);
value = vmOption.substring(eqIdx + 1);
}
if (value == null) {
value = "true";
}
int index = key.indexOf('.');
String group = key;
if (index >= 0) {
group = group.substring(0, index);
}
if ("log".equals(group)) {
if (key.endsWith(".level")) {
try {
Level.parse(value);
builder.option(key, value);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException(String.format("Invalid log level %s specified. %s'", vmOption, e.getMessage()));
}
return;
} else if ("log.file".equals(key)) {
OutputStream out;
try {
out = new BufferedOutputStream(Files.newOutputStream(Paths.get(value), StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.APPEND));
} catch (IOException e) {
throw new IllegalArgumentException("Cannot use the specified log.file", e);
}
builder.logHandler(out);
return;
}
}
OptionDescriptor descriptor = findOptionDescriptor(group, key);
if (descriptor == null) {
key = JAVA_LANGUAGE_ID + "." + key;
descriptor = findOptionDescriptor(JAVA_LANGUAGE_ID, key);
if (descriptor == null) {View on GitHub (pinned to a66e9ccd1d)
Solutions
- Use a valid java.util.logging.Level value: OFF, SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, ALL, or an integer like '700'
- If you need TRACE/DEBUG-style granularity, map it to FINEST/FINE instead of passing the log4j name verbatim
- Verify the value with Level.parse(value) in your own option handling before handing it to the builder
Example fix
// before
builder.option("java.log.espresso.level", "DEBUG"); // not a JUL level
// after
builder.option("java.log.espresso.level", "FINE"); // valid java.util.logging level Defensive patterns
Strategy: validation
Validate before calling
try { java.util.logging.Level.parse(value); }
catch (IllegalArgumentException e) { throw new IllegalArgumentException("Not a JUL level: " + value, e); }
builder.option("java.log.<cat>.level", value); Try / catch
catch (IllegalArgumentException e) { log warning and fall back to "INFO" or fail fast on config } Prevention
- Whitelist the nine JUL level names plus integers in config schemas
- Map log4j/slf4j level names (TRACE->FINEST, DEBUG->FINE, ERROR->SEVERE) at your config boundary
When it happens
Trigger: Passing a builder option like "java.log.<category>.level" whose value is not a valid java.util.logging level: misspelled names (e.g. 'WARN' instead of 'WARNING'), log4j/slf4j level names ('TRACE', 'DEBUG', 'ERROR'), or a non-numeric garbage string.
Common situations: Copying log level names from log4j2/slf4j configuration into Espresso VM options; using 'VERBOSE' which is not a JUL level; copy-paste of option values between -H: logging flags (HotSpot style) and Espresso's java.* options.
Related errors
- Cannot use the specified log.file
- Unrecognized VM option: '
- Invalid VM option %s specified. %s
- LogFile substitution %s cannot be combined with any other ch
- --java.SpecCompliance: Mode can be 'strict' or 'hotspot'.
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/c363ac4dc2e1b4c9.
Report an issue: GitHub.