oracle/graal · error · IllegalArgumentException
Invalid JDWP option value: {key} can be only 'y' or 'n'.
Error message
Invalid JDWP option value: {key} can be only 'y' or 'n'. What it means
Inside the JDWPOptions OptionType converter, yesOrNo() validates that boolean JDWP keys ('server', 'suspend', 'includevirtualthreads') have exactly the single-letter value 'y' or 'n'. Any other value (yes/no, true/false, 1/0) is rejected.
Source
Thrown at espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/EspressoOptions.java:400
@Option(help = "Minimum number of locals to run liveness analysis.\\n" + //
"Liveness analysis, if enabled, only affects compiled code.", //
category = OptionCategory.EXPERT, //
stability = OptionStability.EXPERIMENTAL, //
usageSyntax = "[0, 65535]") //
public static final OptionKey<Integer> LivenessAnalysisMinimumLocals = new OptionKey<>(8);
@Option(help = "Enable Class Hierarchy Analysis, which optimizes instanceof checks and virtual method calls by keeping track of descendants of a given class or interface.", //
category = OptionCategory.EXPERT, //
stability = OptionStability.EXPERIMENTAL, //
usageSyntax = "false|true") //
public static final OptionKey<Boolean> CHA = new OptionKey<>(true);
private static final OptionType<com.oracle.truffle.espresso.jdwp.api.JDWPOptions> JDWP_OPTIONS_OPTION_TYPE = new OptionType<>("JDWPOptions", new Function<String, JDWPOptions>() {
private boolean yesOrNo(String key, String value) {
if (!"y".equals(value) && !"n".equals(value)) {
throw new IllegalArgumentException("Invalid JDWP option value: " + key + " can be only 'y' or 'n'.");
}
return "y".equals(value);
}
@Override
public JDWPOptions apply(String s) {
final String[] options = s.split(",");
String transport = null;
String host = null;
int port = 0;
boolean server = false;
boolean suspend = true;
for (String keyValue : options) {
int equalsIndex = keyValue.indexOf('=');
if (equalsIndex <= 0) {
throw new IllegalArgumentException("JDWP options must be a comma separated list of key=value pairs.");
}View on GitHub (pinned to a66e9ccd1d)
Solutions
- Use single letters exactly: server=y, suspend=n.
- Drop the key entirely when the default is acceptable (suspend defaults to y, server to n).
- Validate the option string with a regex before launching.
Example fix
# before --vm.D...=... --java.JDWPOptions=transport=dt_socket,server=yes,address=:8000 # after --java.JDWPOptions=transport=dt_socket,server=y,address=:8000
Defensive patterns
Strategy: validation
Validate before calling
for (String kv : opts.split(",")) {
String[] p = kv.split("=", 2);
if (Set.of("server","suspend","includevirtualthreads").contains(p[0])
&& !p[1].equals("y") && !p[1].equals("n")) {
throw new ConfigException(kv + " must be y or n");
}
} Type guard
static boolean validJdwp(String s) {
return s.matches("([a-z]+=(y|n|dt_socket|[\w.\[\]:]*\d+),?)*");
} Prevention
- Always use single-letter y/n in JDWP strings.
- Copy from the option's usageSyntax example, not from generic JDK docs.
When it happens
Trigger: Setting --java.JDWPOptions=...,server=yes or suspend=true, or using 'Y'/'N' uppercase - the check is case-sensitive exact match on 'y'/'n'.
Common situations: Copy-pasting agentlib strings from tutorials that use yes/no; translating JDWP options from other tools' formats; uppercase normalization by config management tools.
Related errors
- JDWP options must be a comma separated list of key=value pai
- Invalid JDWP option, address: {value}. Must be in the 0 - 65
- Invalid JDWP option, address: {value}. Port is not a number.
- Invalid transport {value}. Espresso only supports dt_socket
- Invalid JDWP option: {key}. Supported options: 'transport',
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/1fdc408c815918c8.
Report an issue: GitHub.