🔴 The Error You're Seeing
Confirm this matches your console output. If it does, you're in the right place.
java.lang.IllegalArgumentException: Illegal Capacity: -1
at java.base/java.util.ArrayList.<init>(ArrayList.java:161)⚡ Quick Fix Works 80% of the time
Clamp computed capacities to zero or more.
List<Row> buffer = new ArrayList<>(Math.max(0, estimatedRows));🧠 Why this Happens
Tap to expand the deep technical explanation
ArrayList(int initialCapacity) executes elementData = new Object[initialCapacity] immediately, and JVM array creation requires length >= 0. The constructor validates up-front with the fixed string "Illegal Capacity: " so callers get the argument name in the message. Typical sources: size arithmetic like listB.size() - listA.size() going negative, or sentinel -1 flowing from unset config.
The HITEC City Parking Spot Analogy:
A blueprint specifying a room of minus ten square meters - the builder stops before pouring concrete.
🔁 How to Reproduce Confirm this is your error
List<String> l = new ArrayList<>(-1); // IllegalArgumentException: Illegal Capacity: -1
🛠️ Solutions (5 Ways to Fix)
Clamp with Math.max(0, n)
👉 Use this if the estimate can legitimately compute to zero or below.
Zero capacity is legal and defers allocation until the first add, so max(0, ...) preserves behavior while blocking negatives.
var buf = new ArrayList<Row>(Math.max(0, rowsB.size() - rowsA.size()));Derive capacity from actual data sizes
👉 Use this if sizing from another collection.
Passing other.size() directly is always >= 0 and usually accurate; avoid derived arithmetic unless profiling demands it.
List<Row> copy = new ArrayList<>(source.size());
copy.addAll(source);Default constructor when unknown
👉 Use this if no estimate exists.
Growth policy gives amortized O(1) appends; guessing capacities adds risk without measurable gain.
List<Event> events = new ArrayList<>();Long intermediates for big products
👉 Use this if capacity multiplies factors like rows * columns.
Compute in long, bound-check against known limits, then narrow - overflow cannot silently produce negative ints.
long est = (long) files * avgLines;
int cap = est > 5_000_000 ? 5_000_000 : (int) est;Unit-test size calculators
👉 Use this if capacity formulas live in shared utilities.
Boundary tests (0, 1, Integer.MAX_VALUE, huge inputs) catch sign errors long before production allocations explode.
@Test void capacityNeverNegative() {
assertTrue(calcCapacity(-5) >= 0);
}📋 Version Notes
Same wording; allocation immediate for positive capacities.
Unchanged. Capacity 0 defers array allocation until first add (lazy since Java 8).
🛡️ How to Prevent This Next Time
Validate every numeric constructor argument at the layer where it is produced; treat subtraction-based sizes with suspicion.