apache/cassandra · error · MarshalException

Required elements, but saw

Error message

Required %d elements, but saw %d

What it means

The private check(List<?>) helper validates that a decomposed element list has exactly as many entries as the vector's dimension, throwing MarshalException otherwise. It guards internal composition paths (e.g. MultiElements.DelayedValue) that assemble vector values from term lists.

Solutions

  1. Supply exactly `dimension` elements in the vector literal or bound list
  2. Check the column's dimension via the schema (system_schema.columns / DESCRIBE) before building values
  3. If the required size legitimately changed, ALTER the column type

Example fix

// before
// column vector<int, 3>
INSERT INTO t (v) VALUES ([1, 2]);
// after
INSERT INTO t (v) VALUES ([1, 2, 3]);
Defensive patterns

Strategy: validation

Validate before calling

if (values.size() != dimension)
    throw new IllegalArgumentException("vector requires " + dimension + " elements, got " + values.size());

Try / catch

try { /* execute statement with vector literal */ } catch (MarshalException e) { /* fix literal size and retry */ }

Prevention

When it happens

Trigger: Executing an INSERT/UPDATE with a vector literal or bound terms whose element count differs from the declared dimension, e.g. [1, 2, 3] against vector<int, 2>.

Common situations: Hand-written CQL vector literals with the wrong element count; application code assembling bind-marker lists of the wrong size; schema drift between application and table.

Understand the failure class

Background: Tensor shape mismatch errors ("must have shape", "expected shape ... got ..."): when tensor dimensions disagree with what an op or layer was told to expect — this error's family across 6 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/3feaa9cc6af17f97. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/db/marshal/VectorType.java:366

        return Objects.hash(elementType, dimension);
    }

    @Override
    public String toString()
    {
        return toString(false);
    }

    @Override
    public String toString(boolean ignoreFreezing)
    {
        return getClass().getName() + TypeParser.stringifyVectorParameters(elementType, ignoreFreezing, dimension);
    }

    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()

View on GitHub (pinned to 88fd0f6a0e)