apache/cassandra · error · IllegalArgumentException
Reader index should be non-negative, but was
Error message
Reader index should be non-negative, but was ${readerIndex} What it means
VIntCoding.getUnsignedVInt(ByteBuffer,...) requires readerIndex >= 0 to be able to read the first varint byte; a negative index is a caller bug, so it throws IllegalArgumentException with the offending index. Negative indexes cannot address a ByteBuffer.
Solutions
- Validate readerIndex >= 0 before calling, or take readerIndex directly from input.position().
- Fix the offset computation that produced the negative value.
- Use the accessor-free path with ByteBuffer.position() instead of hand-managed indexes when unsure.
Example fix
// before long value = VIntCoding.getUnsignedVInt(input, index, input.limit()); // after int idx = Math.max(0, index); long value = VIntCoding.getUnsignedVInt(input, idx, input.limit());
Defensive patterns
Strategy: validation
Validate before calling
if (readerIndex < 0 || readerIndex > input.limit()) throw new IllegalArgumentException("bad readerIndex " + readerIndex); Try / catch
try { long v = VIntCoding.getUnsignedVInt(buf, idx, buf.limit()); } catch (IllegalArgumentException e) { throw new CorruptFrameException(e); } Prevention
- Derive readerIndex from input.position() instead of manual subtraction.
- Track decode offsets with non-decreasing counters and bounds checks each step.
When it happens
Trigger: Passing readerIndex < 0 to getUnsignedVInt(ByteBuffer, int, int), typically from a buffer position that was computed by subtraction, or a decoding loop decrementing past 0.
Common situations: Custom protocol framing code computing offsets from lengths; reusing a readerIndex variable from a previous frame; off-by-one subtraction in parsers.
Related errors
- ${value}
- A CounterId representation is exactly
- Corrupt HintsDescriptor serialization, problem:
- Expected 1 byte for a tinyint
- Expected 1 or 0 byte value
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/fd1087dee227feee.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/utils/vint/VIntCoding.java:239
public static int getVInt32(ByteBuffer input, int readerIndex)
{
return checkedCast(decodeZigZag64(getUnsignedVInt(input, readerIndex)));
}
public static long getVInt(ByteBuffer input, int readerIndex)
{
return decodeZigZag64(getUnsignedVInt(input, readerIndex));
}
public static long getUnsignedVInt(ByteBuffer input, int readerIndex)
{
return getUnsignedVInt(input, readerIndex, input.limit());
}
public static long getUnsignedVInt(ByteBuffer input, int readerIndex, int readerLimit)
{
if (readerIndex < 0)
throw new IllegalArgumentException("Reader index should be non-negative, but was " + readerIndex);
if (readerIndex >= readerLimit)
return -1;
int firstByte = input.get(readerIndex++);
//Bail out early if this is one byte, necessary or it fails later
if (firstByte >= 0)
return firstByte;
int size = numberOfExtraBytesToRead(firstByte);
if (readerIndex + size > readerLimit)
return -1;
long retval = firstByte & firstByteValueMask(size);
for (int ii = 0; ii < size; ii++)
{
byte b = input.get(readerIndex++);View on GitHub (pinned to 88fd0f6a0e)