apache/cassandra · error · java.lang.IllegalArgumentException

Invalid duration: value must be non-negative

Error message

Invalid duration: value must be non-negative

What it means

The numeric validateQuantity overload rejects negative quantities for duration specs. Durations in Cassandra config must be non-negative; -1 is not a valid disable marker here. Thrown as IllegalArgumentException.

Source

Thrown at src/java/org/apache/cassandra/config/DurationSpec.java:120

    private static String acceptedUnits(TimeUnit minUnit)
    {
        TimeUnit[] units = TimeUnit.values();
        return Arrays.toString(Arrays.copyOfRange(units, minUnit.ordinal(), units.length));
    }

    private static void validateQuantity(String value, long quantity, TimeUnit sourceUnit, TimeUnit minUnit, long max)
    {
        // no need to validate for negatives as they are not allowed at first place from the regex

        if (minUnit.convert(quantity, sourceUnit) >= max)
            throw new IllegalArgumentException("Invalid duration: " + value + ". It shouldn't be more than " +
                                             (max - 1) + " in " + toLowerCaseLocalized(minUnit.name()));
    }

    private static void validateQuantity(long quantity, TimeUnit sourceUnit, TimeUnit minUnit, long max)
    {
        if (quantity < 0)
            throw new IllegalArgumentException("Invalid duration: value must be non-negative");

        if (minUnit.convert(quantity, sourceUnit) >= max)
            throw new IllegalArgumentException(String.format("Invalid duration: %d %s. It shouldn't be more than %d in %s",
                                                           quantity, toLowerCaseLocalized(sourceUnit.name()),
                                                           max - 1, toLowerCaseLocalized(minUnit.name())));
    }

    // get vs no-get prefix is not consistent in the code base, but for classes involved with config parsing, it is
    // imporant to be explicit about get/set as this changes how parsing is done; this class is a data-type, so is
    // not nested, having get/set can confuse parsing thinking this is a nested type
    public long quantity()
    {
        return quantity;
    }

    public TimeUnit unit()
    {
        return unit;

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Replace negative values with 0 (or the property's documented disable value)
  2. Clamp computed durations with Math.max(0, value) before assignment
  3. Use the property's documented mechanism for disabling instead of a negative duration

Example fix

// before
spec.set(retryDelaySeconds);
// after
spec.set(Math.max(0, retryDelaySeconds));
Defensive patterns

Strategy: validation

Validate before calling

static long requireNonNegative(long v) {
    if (v < 0) throw new IllegalArgumentException("Duration must be non-negative");
    return v;
}

Try / catch

try {
    spec.set(value);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("non-negative"))
        logger.error("Negative duration passed: {}", value);
}

Prevention

When it happens

Trigger: Calling a DurationSpec subclass constructor or setter with a negative long, e.g. new SomeDurationSpec(-1, TimeUnit.SECONDS) or programmatically assigning a negative value via a config mutation API.

Common situations: Using -1 to mean 'infinite/disabled' in code that programmatically builds config; sign errors when computing durations dynamically.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/ff3d1b5dbf2f0911. Report an issue: GitHub.