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
- Clamp computed durations to >= -1 before constructing: `Math.max(d, -1)`.
- If -1 means unspecified in your context, pass TimeValue.MINUS_ONE explicitly.
- Audit the upstream setting: search the cluster settings for any negative numeric value.
- 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
- Clamp computed durations with `Math.max(d, -1)` before constructing TimeValue.
- Treat -1 as a sentinel for unspecified/infinite; never pass it through arithmetic.
- Validate configuration inputs at the boundary before they reach TimeValue.
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
- time value cannot store values greater than 106751 days
- failed to parse setting [{}] with value [{}] as a time value
- classname is a required setting for esplugin
- classname is a forbidden for stable esplugin
- invalid deploymentTarget '{}', expected one of {}
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/a60225031eae7fc0.
Report an issue: GitHub.