apache/dubbo · error · IllegalArgumentException

delta {delta} < 0

Error message

delta {delta} < 0

What it means

Thrown by AtomicPositiveInteger.getAndAdd when delta is negative. getAndAdd atomically adds delta and returns the prior value; a negative delta could drive the underlying field negative, breaking the non-negative masking guarantee, so it is rejected outright. Note that unlike AtomicInteger, this class forbids subtraction entirely.

Source

Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/utils/AtomicPositiveInteger.java:73

    }

    public final void set(int newValue) {
        if (newValue < 0) {
            throw new IllegalArgumentException("new value " + newValue + " < 0");
        }
        INDEX_UPDATER.set(this, newValue);
    }

    public final int getAndSet(int newValue) {
        if (newValue < 0) {
            throw new IllegalArgumentException("new value " + newValue + " < 0");
        }
        return INDEX_UPDATER.getAndSet(this, newValue) & Integer.MAX_VALUE;
    }

    public final int getAndAdd(int delta) {
        if (delta < 0) {
            throw new IllegalArgumentException("delta " + delta + " < 0");
        }
        return INDEX_UPDATER.getAndAdd(this, delta) & Integer.MAX_VALUE;
    }

    public final int addAndGet(int delta) {
        if (delta < 0) {
            throw new IllegalArgumentException("delta " + delta + " < 0");
        }
        return INDEX_UPDATER.addAndGet(this, delta) & Integer.MAX_VALUE;
    }

    public final boolean compareAndSet(int expect, int update) {
        if (update < 0) {
            throw new IllegalArgumentException("update value " + update + " < 0");
        }
        return INDEX_UPDATER.compareAndSet(this, expect, update);
    }

View on GitHub (pinned to 3a3043227f)

Solutions

  1. Use decrementAndGet() or getAndDecrement() for subtraction — these mask the result to stay non-negative.
  2. If the delta is genuinely variable, split: if delta >= 0 use getAndAdd(delta), else call getAndDecrement() |delta| times or reconsider the data structure.
  3. Switch to AtomicInteger if negative values are legitimately needed.

Example fix

// before
api.getAndAdd(-1); // throws

// after
api.getAndDecrement(); // non-negative masking built in
Defensive patterns

Strategy: validation

Validate before calling

int delta = /* ... */;
if (delta < 0) {
    throw new IllegalArgumentException("getAndAdd needs delta >= 0; use getAndDecrement to subtract");
}
int prev = api.getAndAdd(delta);

Type guard

static boolean isNonNegativeDelta(int d) { return d >= 0; }

Prevention

When it happens

Trigger: AtomicPositiveInteger.getAndAdd(delta) where delta < 0. Any code path that attempts to decrement via getAndAdd (rather than decrementAndGet, which masks the result) hits this guard.

Common situations: Porting code from AtomicInteger that used getAndAdd(-1) for decrementing; using a computed delta whose sign is wrong; generic algorithms that pass deltas that can go negative. This indicates the caller assumed AtomicInteger semantics.

Related errors


AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14). Data as JSON: /api/errors/0317de1af2e96b36. Report an issue: GitHub.