{"record":{"id":"61a0f0b07b9e1cfe","repo":"apache/cassandra","slug":"invalid-unset-value-for-tuple-field-number-d","errorCode":null,"errorMessage":"Invalid unset value for tuple field number %d","messagePattern":"Invalid unset value for tuple field number (.+?)","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/db/marshal/TupleType.java","lineNumber":417,"sourceCode":"    @Override\n    public List<byte[]> filterSortAndValidateElementsFromArrays(List<byte[]> buffers)\n    {\n        return filterSortAndValidateElements(buffers, ByteArrayUtil.UNSET_BYTE_ARRAY, ByteArrayAccessor.instance);\n    }\n\n    private <T> List<T> filterSortAndValidateElements(List<T> buffers, T unsetValue, ValueAccessor<T> valueAccessor)\n    {\n        if (buffers.size() > size())\n            throw new MarshalException(String.format(\"Tuple value contains too many fields (expected %s, got %s)\", size(), buffers.size()));\n\n        for (int i = 0; i < buffers.size(); i++)\n        {\n            // Since A tuple value is always written in its entirety Cassandra can't preserve a pre-existing value by 'not setting' the new value. Reject the query.\n            T buffer = buffers.get(i);\n            if (buffer == null)\n                continue;\n            if (buffer == unsetValue)\n                throw new InvalidRequestException(String.format(\"Invalid unset value for tuple field number %d\", i));\n            type(i).validate(buffer, valueAccessor);\n        }\n\n        return buffers;\n    }\n\n    @Override\n    public <V> String getString(V input, ValueAccessor<V> accessor)\n    {\n        if (input == null)\n            return \"null\";\n\n        StringBuilder sb = new StringBuilder();\n        int offset = 0;\n        for (int i = 0; i < size(); i++)\n        {\n            if (accessor.isEmptyFromOffset(input, offset))\n                return sb.toString();","sourceCodeStart":399,"sourceCodeEnd":435,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/db/marshal/TupleType.java#L399-L435","documentation":"During filterSortAndValidateElements, a field buffer equal to the sentinel unset marker (UNSET_BYTE_ARRAY) is rejected with InvalidRequestException. Cassandra writes tuples in their entirety, so an 'unset' individual field cannot preserve a previous value; the driver must instead omit or fully supply the tuple.","triggerScenarios":"Binding a query where a driver sends an unset marker for one tuple element (common when using bind markers with partial assignment); calling filterSortAndValidateElements with the unset sentinel present in the buffers list.","commonSituations":"Using prepared statements where some bound variables are left unset inside a tuple value; ORMs or client libraries that map nulls to unset markers; partial-update logic applied to a tuple column.","solutions":["Supply a complete tuple value (all fields set, or the whole tuple null) instead of per-field unset markers","Rewrite the update to replace the whole tuple in one statement","If a partial update is needed, read-modify-write: SELECT the tuple, merge in the app, UPDATE the full value","Check driver documentation for how it encodes unset values and avoid it for tuple fields"],"exampleFix":"// before: binding with unset field\nstmt.bind(id, UNSET, value);\n// after: bind the whole tuple or null\nTupleValue full = elementType.newValue(null, value); // explicit full tuple\nstmt.bind(id, full);","handlingStrategy":"validation","validationCode":"for (Object f : fields)\n    if (f == null || isUnsetMarker(f))\n        throw new IllegalArgumentException(\"tuples cannot contain unset fields; supply the full value\");","typeGuard":null,"tryCatchPattern":"try {\n    tupleType.bind(fields);\n} catch (InvalidRequestException e) {\n    // unset field inside tuple: rewrite as full tuple or whole-column update\n}","preventionTips":["Always write tuples atomically as complete values","Avoid mapping per-field bind markers onto tuple columns","Implement partial updates as read-modify-write of the whole tuple"],"tags":["tuple","unset-value","cql"],"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-17T15:17:12.973Z"}