apache/kafka · error · SchemaException
Bytes size ${size} cannot be negative
Error message
Bytes size ${size} cannot be negative What it means
Thrown by BYTES.read() when the INT32 size prefix decoded to a negative value. The BYTES type encodes length as a signed INT32 and does not support a null sentinel, so a negative size indicates either a NULLABLE_BYTES field (size -1 means null) was misread as BYTES, or the buffer is corrupt/misaligned. Raised as a SchemaException before any bytes are sliced.
Source
Thrown at clients/src/main/java/org/apache/kafka/common/protocol/types/Type.java:697
"A null string is represented with a length of 0.";
}
};
public static final DocumentedType BYTES = new DocumentedType() {
@Override
public void write(ByteBuffer buffer, Object o) {
ByteBuffer arg = (ByteBuffer) o;
int pos = arg.position();
buffer.putInt(arg.remaining());
buffer.put(arg);
arg.position(pos);
}
@Override
public Object read(ByteBuffer buffer) {
int size = buffer.getInt();
if (size < 0)
throw new SchemaException("Bytes size " + size + " cannot be negative");
return bytesRead(buffer, size);
}
@Override
public int sizeOf(Object o) {
ByteBuffer buffer = (ByteBuffer) o;
return 4 + buffer.remaining();
}
@Override
public String typeName() {
return "BYTES";
}
@Override
public ByteBuffer validate(Object item) {
if (item instanceof ByteBuffer)View on GitHub (pinned to c31c9215e1)
Solutions
- Switch the reader to NULLABLE_BYTES if the field can legitimately be null at the negotiated API version.
- Re-decode preceding fields to confirm the buffer position is correct at the failing field.
- Match client and broker versions for the API key to ensure the size prefix encoding agrees.
- Inspect the raw bytes at the failure offset for corruption.
Example fix
// before: decoding a possibly-null byte field as BYTES Object v = Type.BYTES.read(buffer); // throws on size == -1 // after: use the nullable variant Object v = Type.NULLABLE_BYTES.read(buffer); // size -1 -> null
Defensive patterns
Strategy: try-catch
Validate before calling
// BYTES.read() reads the INT32 size internally; a negative size is corrupt
// and there is no public pre-validation hook without duplicating getInt().
try {
java.nio.ByteBuffer value = (java.nio.ByteBuffer) org.apache.kafka.common.protocol.types.Type.BYTES.read(buffer);
} catch (org.apache.kafka.common.protocol.types.SchemaException e) {
// recover
} Try / catch
try {
java.nio.ByteBuffer value = (java.nio.ByteBuffer) org.apache.kafka.common.protocol.types.Type.BYTES.read(buffer);
} catch (org.apache.kafka.common.protocol.types.SchemaException e) {
if (e.getMessage().contains("cannot be negative")) {
throw new IllegalArgumentException("Malformed BYTES field: negative size", e);
}
throw e;
} Prevention
- For fields that may legitimately be null, use NULLABLE_BYTES (sentinel size -1) instead of BYTES — only NULLABLE_BYTES treats -1 as null.
- A negative INT32 size on BYTES.read is wire corruption; close/discard the frame rather than retrying.
- Pair this catch with a buffer-position reset (or mark/reset) so downstream parsing isn't left mid-field.
When it happens
Trigger: BYTES.read(buffer) where buffer.getInt() < 0. Reached when a field encoded as NULLABLE_BYTES is decoded with the non-nullable BYTES type, or when an earlier field's mis-decoded length shifted the position so the size prefix lands on non-length bytes.
Common situations: Schema/nullable mismatch between writer and reader (e.g. API version bump that introduced nullability on a byte-array field). Buffer position corruption from an earlier wrong-length field. Custom interceptors rewriting the payload.
Related errors
- Error reading bytes of size ${size}, only ${remaining} bytes
- String length ${length} cannot be negative
- Buffer underflow while parsing consumer protocol's header
- Malformed consumer protocol subscription
- Malformed consumer protocol assignment
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/6227d871928187f3.json.
Report an issue: GitHub.