apache/kafka · error · SchemaException

String length ${length} cannot be negative

Error message

String length ${length} cannot be negative

What it means

Thrown by STRING.read() when the INT16 length prefix decoded to a negative value. The legacy STRING type stores length as a signed short, so a negative prefix indicates either a deliberately 'null-like' sentinel used by NULLABLE_STRING was misread as STRING, or the buffer is misaligned/corrupt. Raised as a SchemaException before any bytes are consumed.

Source

Thrown at clients/src/main/java/org/apache/kafka/common/protocol/types/Type.java:496

                    "The values are encoded using eight bytes in network byte order (big-endian).";
        }
    };

    public static final DocumentedType STRING = new DocumentedType() {
        @Override
        public void write(ByteBuffer buffer, Object o) {
            byte[] bytes = Utils.utf8((String) o);
            if (bytes.length > Short.MAX_VALUE)
                throw new SchemaException("String length " + bytes.length + " is larger than the maximum string length.");
            buffer.putShort((short) bytes.length);
            buffer.put(bytes);
        }

        @Override
        public String read(ByteBuffer buffer) {
            short length = buffer.getShort();
            if (length < 0)
                throw new SchemaException("String length " + length + " cannot be negative");
            return stringRead(buffer, length);
        }

        @Override
        public int sizeOf(Object o) {
            return 2 + Utils.utf8Length((String) o);
        }

        @Override
        public String typeName() {
            return "STRING";
        }

        @Override
        public String validate(Object item) {
            if (item instanceof String)
                return (String) item;
            else

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Confirm the field is encoded as STRING and not NULLABLE_STRING/COMPACT_STRING; switch the schema to the nullable variant if nulls are expected.
  2. Verify buffer.position() is at the start of the field; rewind and re-decode the preceding fields to find misalignment.
  3. Ensure reader and writer use the same API key and version so the field's encoding matches.
  4. Inspect the raw bytes around the failure to rule out wire corruption.

Example fix

// before: decoding a possibly-null field as STRING
String v = Type.STRING.read(buffer); // throws on length == -1

// after: use the nullable variant for fields that may be absent
String v = Type.NULLABLE_STRING.read(buffer); // length -1 -> null
Defensive patterns

Strategy: try-catch

Validate before calling

// The negative length is read internally by STRING.read() via buffer.getShort();
// there is no public hook to pre-validate it without duplicating the read.
// If you own the buffer you *could* peek+validate, but try/catch is the contract.
try {
    String value = (String) org.apache.kafka.common.protocol.types.Type.STRING.read(buffer);
} catch (org.apache.kafka.common.protocol.types.SchemaException e) {
    // recover: reset buffer / skip field / close connection
}

Try / catch

try {
    String value = (String) org.apache.kafka.common.protocol.types.Type.STRING.read(buffer);
} catch (org.apache.kafka.common.protocol.types.SchemaException e) {
    if (e.getMessage().contains("cannot be negative")) {
        // truncated or hostile frame — do not retry the same buffer
        throw new IllegalArgumentException("Malformed STRING field: negative length", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: STRING.read(buffer) where buffer.getShort() returns < 0. Commonly happens when a field encoded as NULLABLE_STRING (length -1 means null) is decoded with the STRING type instead, or when the buffer position is off by one or more bytes due to an earlier mis-decoded field.

Common situations: Decoding a nullable string column with the wrong schema (STRING vs NULLABLE_STRING). Schema mismatch between writer and reader (e.g. API version change that introduced nullability). Buffer corruption or accidental reuse of a buffer whose position was not rewound.

Related errors


AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03). Data as JSON: /data/errors/e4020bbca048e12c.json. Report an issue: GitHub.