oracle/graal · error · IllegalArgumentException

Len must be non negative but was %d

Error message

Len must be non negative but was %d

What it means

The byte[]-backed BinaryInput implementation rejects negative lengths in read(byte[], int, int) with IllegalArgumentException('Len must be non negative but was %d') before any bounds check. It is a fail-fast precondition on the marshalling API, guarding the subsequent pos+len arithmetic and arraycopy.

Source

Thrown at compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/BinaryInput.java:560

        }

        ByteArrayBinaryInput(byte[] buffer, int length) {
            super(length);
            this.buffer = buffer;
        }

        @Override
        public int read() {
            if (pos >= length) {
                return EOF;
            }
            return (buffer[pos++] & 0xff);
        }

        @Override
        public void read(byte[] b, int off, int len) {
            if (len < 0) {
                throw new IllegalArgumentException(String.format("Len must be non negative but was %d", len));
            }
            if (pos + len > length) {
                throw new IndexOutOfBoundsException();
            }
            System.arraycopy(buffer, pos, b, off, len);
            pos += len;
        }

        @Override
        public ByteBuffer asByteBuffer(int len) {
            ByteBuffer result = ByteBuffer.wrap(buffer, pos, len).slice().asReadOnlyBuffer();
            pos += len;
            return result;
        }
    }

    private static final class CCharPointerInput extends BinaryInput {

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Clamp or validate the computed length: len = Math.max(0, total - alreadyRead) before calling read.
  2. Fix the loop condition that let len go negative (use while (remaining > 0)).
  3. Validate protocol length fields at the boundary before translating them into read calls.
  4. Add an assertion/log of (pos, len, length) at the call site to catch underflow early.

Example fix

// before
in.read(b, off, total - alreadyRead);
// after
int len = Math.max(0, total - alreadyRead);
if (len > 0) in.read(b, off, len);
Defensive patterns

Strategy: validation

Validate before calling

if (len < 0) throw new IllegalArgumentException("bad len: " + len);
in.read(b, off, len);

Try / catch

try {
    in.read(b, off, len);
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Len must be non negative")) {
        // fix caller's length arithmetic; do not retry with the same len
    }
}

Prevention

When it happens

Trigger: Calling read(b, off, len) (or an array-read helper that forwards to it, e.g. read(boolean[], int, int)) with a negative len value, often from a computed length like remaining()-alreadyRead.

Common situations: Length arithmetic bugs where a subtraction underflows (reading past a known count), reusing a read loop's len variable after it was decremented to negative, or an upstream protocol field carrying a negative count.

Related errors


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/cbc0aa3c94465852. Report an issue: GitHub.