apache/dubbo · error · IllegalArgumentException
update value {update} < 0
Error message
update value {update} < 0 What it means
Thrown by AtomicPositiveInteger.compareAndSet when the update value is negative. CAS atomically swaps to 'update' only if the current value equals 'expect'; since 'update' must remain non-negative per the class invariant, a negative update is rejected before the CAS is attempted.
Source
Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/utils/AtomicPositiveInteger.java:87
}
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);
}
public final boolean weakCompareAndSet(int expect, int update) {
if (update < 0) {
throw new IllegalArgumentException("update value " + update + " < 0");
}
return INDEX_UPDATER.weakCompareAndSet(this, expect, update);
}
@Override
public byte byteValue() {
return (byte) get();
}
@Override
public short shortValue() {View on GitHub (pinned to 3a3043227f)
Solutions
- Ensure the computed 'update' is always >= 0; mask with (v & Integer.MAX_VALUE) if wraparound is acceptable.
- Rethink the algorithm: AtomicPositiveInteger is designed for round-robin indices that only ever grow/wrap, not arbitrary state machines.
- Switch to AtomicInteger if the value legitimately needs to be negative.
Example fix
// before api.compareAndSet(old, next); // next may be negative // after api.compareAndSet(old, next < 0 ? 0 : next);
Defensive patterns
Strategy: validation
Validate before calling
int update = /* ... */; if (update < 0) update = 0; // or (update & Integer.MAX_VALUE) api.compareAndSet(expect, update);
Type guard
static boolean isNonNegative(int v) { return v >= 0; } Prevention
- Ensure the CAS 'update' target is non-negative; mask if wraparound is acceptable.
- Reconsider the algorithm if it needs negative states — AtomicPositiveInteger only models growing/wrapping indices.
- Use AtomicInteger for arbitrary signed state machines.
When it happens
Trigger: AtomicPositiveInteger.compareAndSet(expect, update) where update < 0. The 'expect' value is not constrained (it may not match), but 'update' must be non-negative.
Common situations: Lock-free algorithm ported from AtomicInteger where the desired new state can be negative; a computed 'update' with a sign error; off-by-one in a CAS loop. Indicates the caller's algorithm is incompatible with the non-negative contract.
Related errors
AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14).
Data as JSON: /api/errors/cc3f9b8604f868dd.
Report an issue: GitHub.