oracle/graal · warning · InvalidArgumentException

invalid double value: "%s"

Error message

invalid double value: "%s"

What it means

InvalidArgumentException from DoubleValue.parseValue: a value string was supplied but Double.valueOf(arg) threw NumberFormatException — the text is not a parsable Java double. The message quotes the offending string, so NaN spellings like 'nan ' with whitespace, localized decimal commas ('0,5'), and trailing units ('0.85x') are all directly visible.

Source

Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/util/args/DoubleValue.java:48

public class DoubleValue extends OptionValue<Double> {
    public DoubleValue(String name, String help) {
        super(name, help);
    }

    public DoubleValue(String name, Double defaultValue, String help) {
        super(name, defaultValue, help);
    }

    @Override
    public boolean parseValue(String arg) throws InvalidArgumentException {
        if (arg == null) {
            throw new InvalidArgumentException(getName(), "no value provided");
        }
        try {
            value = Double.valueOf(arg);
            return true;
        } catch (NumberFormatException e) {
            throw new InvalidArgumentException(getName(), String.format("invalid double value: \"%s\"", arg));
        }
    }
}

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Use a plain dot-decimal number: '0.85', '1e-3', '-2.5'; quote shell expansions and trim whitespace.
  2. Fix the producer of the value (config parser, locale-aware formatting) rather than compensating at the CLI.
  3. If a percentage is natural for users, add a dedicated option type that strips '%' and divides, instead of feeding it to DoubleValue.

Example fix

# before (de_DE locale)
$ tool --threshold=0,85

# after
$ tool --threshold=0.85
Defensive patterns

Strategy: validation

Validate before calling

static String normalizeDecimal(String raw) {
    if (raw == null) return null;
    String t = raw.trim().replace(',', '.');   // handle localized decimal comma
    if (t.endsWith("%")) t = t.substring(0, t.length() - 1);
    if (!t.matches("[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?")) return null; // reject early
    return t;
}

Type guard

static boolean isParsableDouble(String s) {
    if (s == null) return false;
    try { Double.parseDouble(s.trim()); return true; } catch (NumberFormatException e) { return false; }
}

Try / catch

try {
    cmd.parse(args);
} catch (InvalidArgumentException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("invalid double value")) {
        System.err.println(e.getOption() + " expects a dot-decimal number, e.g. 0.85 (got: " + e.getValue() + ")");
    } else throw e;
}

Prevention

When it happens

Trigger: Passing '-opt=0,5' (comma decimal separator from a localized environment), '-opt=85%' , '-opt=1e' or empty string to a DoubleValue option; NumberFormatException is caught and rethrown as InvalidArgumentException with String.format("invalid double value: \"%s\"", arg).

Common situations: Locales that format decimals with commas (de/fr) leaking into arg strings; values read from config files with trailing whitespace or quotes; percentage strings passed where a fraction is expected.

Related errors


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