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

  1. Use a valid java.util.logging.Level value: OFF, SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, ALL, or an integer like '700'
  2. If you need TRACE/DEBUG-style granularity, map it to FINEST/FINE instead of passing the log4j name verbatim
  3. 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

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


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