{"record":{"id":"b1d4a9985687fbb3","repo":"apache/cassandra","slug":"unset-is-not-supported-inside-vectors","errorCode":null,"errorMessage":"unset is not supported inside vectors","messagePattern":"unset is not supported inside vectors","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/db/marshal/VectorType.java","lineNumber":216,"sourceCode":"    @Override\n    public List<byte[]> filterSortAndValidateElementsFromArrays(List<byte[]> buffers)\n    {\n        return filterSortAndValidateElements(buffers, ByteArrayUtil.UNSET_BYTE_ARRAY, ByteArrayAccessor.instance);\n    }\n\n    public <V> List<V> filterSortAndValidateElements(List<V> buffers, V unsetValue, ValueAccessor<V> valueAccessor)\n    {\n        // We only filter and validate for this type.\n        if (buffers == null)\n            return null;\n\n        for (V buffer : buffers)\n        {\n            if (buffer == null || elementType.isNull(buffer, valueAccessor))\n                throw new MarshalException(\"null is not supported inside vectors\");\n\n            if (buffer == unsetValue)\n                throw new InvalidRequestException(\"unset is not supported inside vectors\");\n\n            elementType.validate(buffer, valueAccessor);\n        }\n        return buffers;\n    }\n\n    @Override\n    public <V> ByteSource asComparableBytes(ValueAccessor<V> accessor, V value, ByteComparable.Version version)\n    {\n        if (isNull(value, accessor))\n            return null;\n        ByteSource[] srcs = new ByteSource[dimension];\n        List<V> split = unpack(value, accessor);\n        for (int i = 0; i < dimension; i++)\n            srcs[i] = elementType.asComparableBytes(accessor, split.get(i), version);\n        return ByteSource.withTerminatorMaybeLegacy(version, 0x00, srcs);\n    }\n","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/db/marshal/VectorType.java#L198-L234","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Do not use the unset sentinel inside vector elements; supply concrete values","Validate inputs before binding so unset values never reach vector composition","If a value is unset, skip the whole vector write rather than embedding unset elements"],"exampleFix":"// before\nList<ByteBuffer> elems = List.of(v1, ByteBufferUtil.UNSET_BYTE_BUFFER, v3);\n// after\nList<ByteBuffer> elems = List.of(v1, concreteValue, v3);","handlingStrategy":"validation","validationCode":"boolean hasUnset = elements.stream().anyMatch(b -> b == ByteBufferUtil.UNSET_BYTE_BUFFER);\nif (hasUnset) throw new IllegalArgumentException(\"unset not allowed inside vector elements\");","typeGuard":null,"tryCatchPattern":"try { buf = vt.decompose(elements); } catch (InvalidRequestException e) { /* unset leaked into vector */ }","preventionTips":["Only use UNSET at the top level of bound statements","Resolve unset terms to concrete values before vector composition"],"tags":["cassandra","vector-type","unset","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}