apache/cassandra · error · MarshalException
Unexpected extraneous bytes after value
Error message
Unexpected %s extraneous bytes after %s value
What it means
VectorType throws this MarshalException when a serialized vector value contains more bytes than the declared dimension x element-size requires. Cassandra's vector marshaling requires the byte buffer to be fully consumed after reading all elements; leftover trailing bytes mean the value is malformed or was written by a different type definition.
Solutions
- Check the buffer length equals the exact expected size (dimension * element type size) before passing it to the vector type's validate/decompose methods
- Verify the vector column's dimension and element type in the schema match how the value was produced
- Re-write the affected data with the correct type; if data on disk is corrupted, run scrub or restore from backup
- If from user input, trim or reject values with trailing bytes at parse time
Example fix
// before
ByteBuffer value = ByteBuffer.allocate(20); // 5 floats written, but column is vector<float, 4>
VectorType.getInstance(FloatType.instance, 4).validate(value);
// after
if (value.remaining() != 4 * 4) throw new IllegalArgumentException("expected 16 bytes for vector<float,4>");
VectorType.getInstance(FloatType.instance, 4).validate(value); Defensive patterns
Strategy: validation
Validate before calling
int expected = dimension * elementType.valueLengthIfFixed();
if (value == null || value.remaining() != expected) throw new IllegalArgumentException("expected " + expected + " bytes"); Try / catch
try { vectorType.validate(buffer); } catch (MarshalException e) { log.error("malformed vector value: {}", e.getMessage()); throw new IllegalArgumentException(e); } Prevention
- Compute exact serialized size from dimension and element type before passing buffers
- Don't hand-construct vector byte buffers; use the type's serializer
- Re-check schema dimension after any ALTER TABLE on vector columns
When it happens
Trigger: Calling VectorType.fromString / decompose / validate (via decomposeUn Type) on a buffer whose byte count exceeds dimension * elementLength, e.g. passing a value with extra trailing bytes, or validating a buffer typed as a vector with a smaller dimension than the data was written for.
Common situations: Schema changed a vector column's dimension or element type after data was written; manually constructed ByteBuffers for tests; corrupted SSTable or commit-log data; mixing up fixed-length element types (e.g. float vs double).
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Invalid empty vector value
- Not enough bytes to read a
- Not enough bytes to read a vector<
- Attempted to add float vector of dimension
- cannot parse ' ' as hex bytes
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/453d2cf12010b387.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/db/marshal/VectorType.java:381
private void check(List<?> values)
{
if (values.size() != dimension)
throw new MarshalException(String.format("Required %d elements, but saw %d", dimension, values.size()));
// This code base always works with a list that is RandomAccess, so can use .get to avoid allocation
for (int i = 0; i < dimension; i++)
{
Object value = values.get(i);
if (value == null || (value instanceof ByteBuffer && elementSerializer.isNull((ByteBuffer) value)))
throw new MarshalException(String.format("Element at index %d is null (expected type %s); given %s", i, elementType.asCQL3Type(), values));
}
}
private <V> void checkConsumedFully(V buffer, ValueAccessor<V> accessor, int offset)
{
int remaining = accessor.sizeFromOffset(buffer, offset);
if (remaining > 0)
throw new MarshalException("Unexpected " + remaining + " extraneous bytes after " + asCQL3Type() + " value");
}
private static void rejectNullOrEmptyValue()
{
throw new MarshalException("Invalid empty vector value");
}
@Override
public ByteBuffer getMaskedValue()
{
List<ByteBuffer> values = Collections.nCopies(dimension, elementType.getMaskedValue());
return serializer.pack(values, ByteBufferAccessor.instance);
}
public abstract class VectorSerializer extends TypeSerializer<List<T>>
{
public abstract <VL, VR> int compareCustom(VL left, ValueAccessor<VL> accessorL, VR right, ValueAccessor<VR> accessorR);
View on GitHub (pinned to 88fd0f6a0e)