{"record":{"id":"a60225031eae7fc0","repo":"elastic/elasticsearch","slug":"duration-cannot-be-negative-was-given","errorCode":null,"errorMessage":"duration cannot be negative, was given [{}]","messagePattern":"duration cannot be negative, was given \\[(.+?)\\]","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"libs/core/src/main/java/org/elasticsearch/core/TimeValue.java","lineNumber":46,"sourceCode":"\n    private static final long C0 = 1L;\n    private static final long C1 = C0 * 1000L;\n    private static final long C2 = C1 * 1000L;\n    private static final long C3 = C2 * 1000L;\n    private static final long C4 = C3 * 60L;\n    private static final long C5 = C4 * 60L;\n    private static final long C6 = C5 * 24L;\n\n    private final long duration;\n    private final TimeUnit timeUnit;\n\n    public TimeValue(long millis) {\n        this(millis, TimeUnit.MILLISECONDS);\n    }\n\n    public TimeValue(long duration, TimeUnit timeUnit) {\n        if (duration < -1) {\n            throw new IllegalArgumentException(\"duration cannot be negative, was given [\" + duration + \"]\");\n        }\n        this.duration = duration;\n        this.timeUnit = timeUnit;\n    }\n\n    public static TimeValue timeValueNanos(long nanos) {\n        return new TimeValue(nanos, TimeUnit.NANOSECONDS);\n    }\n\n    public static TimeValue timeValueMillis(long millis) {\n        if (millis == 0) {\n            return ZERO;\n        }\n        if (millis == -1) {\n            return MINUS_ONE;\n        }\n        return new TimeValue(millis, TimeUnit.MILLISECONDS);\n    }","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/core/src/main/java/org/elasticsearch/core/TimeValue.java#L28-L64","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nTimeValue tv = new TimeValue(interval.millis() - margin.millis(), TimeUnit.MILLISECONDS);\n// after\nlong d = interval.millis() - margin.millis();\nTimeValue tv = new TimeValue(Math.max(d, -1), TimeUnit.MILLISECONDS);","handlingStrategy":"validation","validationCode":"static TimeValue safeTimeValue(long duration, TimeUnit unit) {\n    if (duration < -1) {\n        throw new IllegalArgumentException(\"Duration \" + duration + \" is invalid; must be >= -1.\");\n    }\n    return new TimeValue(duration, unit);\n}","typeGuard":"static boolean isValidTimeDuration(long duration) {\n    return duration >= -1;\n}","tryCatchPattern":"try {\n    TimeValue tv = new TimeValue(duration, unit);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"duration cannot be negative\")) {\n        // clamp to -1 (sentinel) or 0 depending on semantics, then retry\n        return TimeValue.MINUS_ONE;\n    }\n    throw e;\n}","preventionTips":["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."],"tags":["core","time-value","validation","configuration","arithmetic"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}