apache/cassandra · error · IllegalArgumentException

Size must be non-negative

Error message

Size must be non-negative (${size})

What it means

BufferPool.get() returns an empty buffer for size == 0 but throws IllegalArgumentException for any negative size, since a negative allocation is meaningless. The pool must reject these early rather than compute an invalid chunk size.

Solutions

  1. Validate size >= 0 before calling BufferPool.get; treat negatives as corruption and fail the read.
  2. Clamp: if (size <= 0) use BufferPool.get(0) (EMPTY_BUFFER) instead of passing the negative value.
  3. Fix the upstream length computation (e.g. endOffset - startOffset) that produced the negative value.

Example fix

// before
ByteBuffer buf = BufferPool.get(length);
// after
if (length < 0) throw new CorruptFileException("negative read length " + length);
ByteBuffer buf = BufferPool.get(length);
Defensive patterns

Strategy: validation

Validate before calling

if (size < 0) throw new IllegalArgumentException("negative size: " + size);

Try / catch

try { return BufferPool.get(size); } catch (IllegalArgumentException e) { throw new CorruptFileException("bad buffer size", e); }

Prevention

When it happens

Trigger: Calling BufferPool.get(size) (or get(size, bufferType) / allocate variants) with size < 0, typically from a computed length like a truncated file size, a serialized length field, or a subtraction that went negative.

Common situations: Corrupt or malicious on-disk length values; reading past EOF yields -1 fed straight into allocate; integer underflow when sizing read buffers.

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/8eaeedab43fdfde1. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/utils/memory/BufferPool.java:939

            else
            {
                if (logger.isTraceEnabled())
                    logger.trace("Requested buffer size {} has been allocated directly due to lack of capacity", prettyPrintMemory(size));
            }

            return allocate(size, BufferType.OFF_HEAP);
        }

        private ByteBuffer tryGet(int size, boolean sizeIsLowerBound)
        {
            LocalPool pool = this;
            if (size <= tinyLimit)
            {
                if (size <= 0)
                {
                    if (size == 0)
                        return EMPTY_BUFFER;
                    throw new IllegalArgumentException("Size must be non-negative (" + size + ')');
                }

                pool = tinyPool();
            }
            else if (size > NORMAL_CHUNK_SIZE)
            {
                metrics.misses.mark();
                return null;
            }

            ByteBuffer ret = pool.tryGetInternal(size, sizeIsLowerBound);
            if (ret != null)
            {
                metrics.hits.mark();
                memoryInUse.inc(ret.capacity());
            }
            else
            {

View on GitHub (pinned to 88fd0f6a0e)