apache/cassandra · error · IllegalArgumentException

All values must be either negative or positive, got %d month

Error message

All values must be either negative or positive, got %d months, %d days, %d nanoseconds

What it means

The driver's Duration type (CQL duration) encodes months, days, and nanoseconds, and its private constructor enforces the invariant that the components must all share a sign — a duration cannot be, say, negative months with positive days, because the resulting ordering would be ambiguous. Mixed-sign components throw IllegalArgumentException with this message.

Source

Thrown at src/java/org/apache/cassandra/cql3/functions/types/Duration.java:89

    private final int months;

    /**
     * The number of days.
     */
    private final int days;

    /**
     * The number of nanoseconds.
     */
    private final long nanoseconds;

    private Duration(int months, int days, long nanoseconds)
    {
        // Makes sure that all the values are negative if one of them is
        if ((months < 0 || days < 0 || nanoseconds < 0)
            && ((months > 0 || days > 0 || nanoseconds > 0)))
        {
            throw new IllegalArgumentException(
            String.format(
            "All values must be either negative or positive, got %d months, %d days, %d nanoseconds",
            months, days, nanoseconds));
        }
        this.months = months;
        this.days = days;
        this.nanoseconds = nanoseconds;
    }

    /**
     * Creates a duration with the given number of months, days and nanoseconds.
     *
     * <p>A duration can be negative. In this case, all the non zero values must be negative.
     *
     * @param months      the number of months
     * @param days        the number of days
     * @param nanoseconds the number of nanoseconds
     * @throws IllegalArgumentException if the values are not all negative or all positive

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Normalize the duration so all three components have the same sign before constructing (flip all or none)
  2. Compute the interval in a single unit (e.g. total nanoseconds or months) and build the Duration from that
  3. Validate inputs in application code before calling Duration.newInstance

Example fix

// before
Duration d = Duration.newInstance(1, -15, 0); // mixed signs
// after
Duration d = Duration.newInstance(-1, -15, 0); // uniformly negative, or recompute in one unit
Defensive patterns

Strategy: validation

Validate before calling

boolean mixedSign = (m < 0 || d < 0 || n < 0) && (m > 0 || d > 0 || n > 0);
if (mixedSign) throw new IllegalArgumentException("duration components must share one sign");

Try / catch

try {
    Duration dur = Duration.newInstance(months, days, nanos);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("negative or positive")) {
        // normalize signs and retry
    }
}

Prevention

When it happens

Trigger: Creating a Duration via Duration.newInstance (or a custom factory) with mixed-sign values such as (2, -3, 0), or decoding an invalid serialized duration containing mixed-sign components.

Common situations: Computing durations by subtracting date components independently (monthsDiff, daysDiff, nanosDiff) so components take opposite signs; hand-crafting durations to represent "backwards" intervals; corrupt binary input.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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