apache/cassandra · error · InvalidRequestException

unset is not supported inside vectors

Error message

unset is not supported inside vectors

What it means

During vector validation, an element buffer that equals the special UNSET marker is rejected with InvalidRequestException. UNSET is only meaningful at the top level of a bound value, not inside a vector, whose elements must all be concrete values.

Source

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

    @Override
    public List<byte[]> filterSortAndValidateElementsFromArrays(List<byte[]> buffers)
    {
        return filterSortAndValidateElements(buffers, ByteArrayUtil.UNSET_BYTE_ARRAY, ByteArrayAccessor.instance);
    }

    public <V> List<V> filterSortAndValidateElements(List<V> buffers, V unsetValue, ValueAccessor<V> valueAccessor)
    {
        // We only filter and validate for this type.
        if (buffers == null)
            return null;

        for (V buffer : buffers)
        {
            if (buffer == null || elementType.isNull(buffer, valueAccessor))
                throw new MarshalException("null is not supported inside vectors");

            if (buffer == unsetValue)
                throw new InvalidRequestException("unset is not supported inside vectors");

            elementType.validate(buffer, valueAccessor);
        }
        return buffers;
    }

    @Override
    public <V> ByteSource asComparableBytes(ValueAccessor<V> accessor, V value, ByteComparable.Version version)
    {
        if (isNull(value, accessor))
            return null;
        ByteSource[] srcs = new ByteSource[dimension];
        List<V> split = unpack(value, accessor);
        for (int i = 0; i < dimension; i++)
            srcs[i] = elementType.asComparableBytes(accessor, split.get(i), version);
        return ByteSource.withTerminatorMaybeLegacy(version, 0x00, srcs);
    }

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Do not use the unset sentinel inside vector elements; supply concrete values
  2. Validate inputs before binding so unset values never reach vector composition
  3. If a value is unset, skip the whole vector write rather than embedding unset elements

Example fix

// before
List<ByteBuffer> elems = List.of(v1, ByteBufferUtil.UNSET_BYTE_BUFFER, v3);
// after
List<ByteBuffer> elems = List.of(v1, concreteValue, v3);
Defensive patterns

Strategy: validation

Validate before calling

boolean hasUnset = elements.stream().anyMatch(b -> b == ByteBufferUtil.UNSET_BYTE_BUFFER);
if (hasUnset) throw new IllegalArgumentException("unset not allowed inside vector elements");

Try / catch

try { buf = vt.decompose(elements); } catch (InvalidRequestException e) { /* unset leaked into vector */ }

Prevention

When it happens

Trigger: Passing the unset sentinel buffer (e.g. ByteBufferUtil.UNSET_BYTE_BUFFER) as an element of a collection bound to a vector column, so filterSortAndValidateElements encounters buffer == unsetValue.

Common situations: Driver/binding code that maps unset query parameters into collection elements; generic code that fills vector slots from bound-term values where some were left unset.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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