elastic/elasticsearch · error · IllegalArgumentException

failed to parse [{}]

Error message

failed to parse [{}]

What it means

Thrown by TimeValue.parse as the final fallback when the numeric prefix of a time value is neither a valid long nor a valid double. The chained NumberFormatException (from the Long attempt) is the cause. This is the catch-all for non-numeric garbage where a unit suffix was recognized but the magnitude was not parseable.

Source

Thrown at libs/core/src/main/java/org/elasticsearch/core/TimeValue.java:431

            final long value = Long.parseLong(s);
            if (value < -1) {
                // -1 is magic, but reject any other negative values
                throw new IllegalArgumentException(
                    "failed to parse setting ["
                        + settingName
                        + "] with value ["
                        + initialInput
                        + "] as a time value: negative durations are not supported"
                );
            }
            return value;
        } catch (final NumberFormatException e) {
            try {
                @SuppressWarnings("unused")
                final double ignored = Double.parseDouble(s);
                throw new IllegalArgumentException("failed to parse [" + initialInput + "], fractional time values are not supported", e);
            } catch (final NumberFormatException ignored) {
                throw new IllegalArgumentException("failed to parse [" + initialInput + "]", e);
            }
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        return this.compareTo(((TimeValue) o)) == 0;
    }

    @Override
    public int hashCode() {
        return Double.hashCode(((double) duration) * timeUnit.toNanos(1));
    }

    public static long nsecToMSec(long ns) {

View on GitHub (pinned to db6a809a66)

Solutions

  1. Inspect the original input echoed in the message — it contains a non-numeric magnitude for a recognized unit.
  2. Strip non-ASCII whitespace and stray symbols; ensure the value matches ^-?\d+(\.[0-9]+)?[a-z]+$ before parsing.
  3. If the value comes from a template, confirm the placeholder was substituted and is not the literal '${...}' string.
  4. Replace the value with a clean integer + unit, e.g. "30s".

Example fix

// before
String t = "${timeout}s"; // unsubstituted placeholder

// after
String t = "30s";
Defensive patterns

Strategy: try-catch

Validate before calling

// Strict whitelist before TimeValue.parseTimeValue
private static final Pattern STRICT_TV =
    Pattern.compile("^(?:-1|0+|-?\\d+(?:ns|us|micros|ms|s|m|h|d))$");
boolean safe(String s) { return s != null && STRICT_TV.matcher(s.trim().toLowerCase(Locale.ROOT)).matches(); }

Type guard

static boolean isParsableTimeValue(String s) {
    if (s == null) return false;
    String n = s.trim().toLowerCase(Locale.ROOT);
    return n.equals("-1") || n.matches("0+") || n.matches("-?\\d+(ns|us|micros|ms|s|m|h|d)");
}

Try / catch

try {
    return TimeValue.parseTimeValue(raw, setting);
} catch (IllegalArgumentException e) {
    log.warn("ignoring unparsable time value for [{}]: [{}]", setting, raw);
    return defaultValue; // only if a documented default is acceptable; otherwise rethrow

Prevention

When it happens

Trigger: Supplying a time value whose unit suffix is recognized (s, ms, m, h, d, nanos, micros) but whose numeric portion is non-numeric, e.g. "abcs", "--ms", "NaNs", "1es". Fires at TimeValue.java:431 after both Long and Double parsing fail.

Common situations: A leading stray character (whitespace handled, but symbols not), an embedded unit, a copy-paste that includes a non-breaking space or comment, a templating system that left a placeholder unsubstituted ("${TIMEOUT}s").

Understand the failure class

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/8d7d79e3e86be59b. Report an issue: GitHub.