elastic/elasticsearch · error · IllegalArgumentException

duration cannot be negative, was given [{}]

Error message

duration cannot be negative, was given [{}]

What it means

Thrown by the TimeValue(long, TimeUnit) constructor when the supplied duration is less than -1. The value -1 is treated as a magic sentinel meaning `unspecified`/`infinite` in many Elasticsearch settings, so it is explicitly permitted; any other negative value is rejected because a negative duration has no meaningful interpretation for timeouts, intervals, or retention periods.

Source

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

    private static final long C0 = 1L;
    private static final long C1 = C0 * 1000L;
    private static final long C2 = C1 * 1000L;
    private static final long C3 = C2 * 1000L;
    private static final long C4 = C3 * 60L;
    private static final long C5 = C4 * 60L;
    private static final long C6 = C5 * 24L;

    private final long duration;
    private final TimeUnit timeUnit;

    public TimeValue(long millis) {
        this(millis, TimeUnit.MILLISECONDS);
    }

    public TimeValue(long duration, TimeUnit timeUnit) {
        if (duration < -1) {
            throw new IllegalArgumentException("duration cannot be negative, was given [" + duration + "]");
        }
        this.duration = duration;
        this.timeUnit = timeUnit;
    }

    public static TimeValue timeValueNanos(long nanos) {
        return new TimeValue(nanos, TimeUnit.NANOSECONDS);
    }

    public static TimeValue timeValueMillis(long millis) {
        if (millis == 0) {
            return ZERO;
        }
        if (millis == -1) {
            return MINUS_ONE;
        }
        return new TimeValue(millis, TimeUnit.MILLISECONDS);
    }

View on GitHub (pinned to db6a809a66)

Solutions

  1. Clamp computed durations to >= -1 before constructing: `Math.max(d, -1)`.
  2. If -1 means unspecified in your context, pass TimeValue.MINUS_ONE explicitly.
  3. Audit the upstream setting: search the cluster settings for any negative numeric value.
  4. For mandatory positive durations, validate `> 0` before constructing.

Example fix

// before
TimeValue tv = new TimeValue(interval.millis() - margin.millis(), TimeUnit.MILLISECONDS);
// after
long d = interval.millis() - margin.millis();
TimeValue tv = new TimeValue(Math.max(d, -1), TimeUnit.MILLISECONDS);
Defensive patterns

Strategy: validation

Validate before calling

static TimeValue safeTimeValue(long duration, TimeUnit unit) {
    if (duration < -1) {
        throw new IllegalArgumentException("Duration " + duration + " is invalid; must be >= -1.");
    }
    return new TimeValue(duration, unit);
}

Type guard

static boolean isValidTimeDuration(long duration) {
    return duration >= -1;
}

Try / catch

try {
    TimeValue tv = new TimeValue(duration, unit);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("duration cannot be negative")) {
        // clamp to -1 (sentinel) or 0 depending on semantics, then retry
        return TimeValue.MINUS_ONE;
    }
    throw e;
}

Prevention

When it happens

Trigger: Passing a computed duration that underflows or is set from a negative config. Subtracting two TimeValues and constructing a new one from the difference without clamping. Parsing logic that maps a missing value to 0 but maps an error to -2.

Common situations: Arithmetic on settings (e.g. `interval - safety_margin` going negative for tiny intervals). Misconfigured negative timeout in YAML. Off-by-one in conversion code treating -1 sentinel as ordinary value.

Related errors


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