{"record":{"id":"5d93ad18347f632a","repo":"apache/cassandra","slug":"invalid-unset-value-for-s","errorCode":null,"errorMessage":"Invalid unset value for %s","messagePattern":"Invalid unset value for (.+?)","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/restrictions/SimpleRestriction.java","lineNumber":344,"sourceCode":"        ByteBuffer buffer = values.bindAndGetSingleTermValue(context);\n        validate(buffer);\n        return buffer;\n    }\n\n    private List<List<ByteBuffer>> bindAndGetElements(FunctionContext context)\n    {\n        List<List<ByteBuffer>> elementsList = values.bindAndGetElements(context);\n        validate(elementsList);\n        elementsList.forEach(this::validateElements);\n        return elementsList;\n    }\n\n    private void validate(List<?> list)\n    {\n        if (list == null)\n            throw invalidRequest(\"Invalid null value for %s\", columnsExpression);\n        if (list == Term.UNSET_LIST)\n            throw invalidRequest(\"Invalid unset value for %s\", columnsExpression);\n    }\n\n    private void validate(ByteBuffer buffer)\n    {\n        if (buffer == null)\n            throw invalidRequest(\"Invalid null value for %s\", columnsExpression);\n        if (buffer == ByteBufferUtil.UNSET_BYTE_BUFFER)\n            throw invalidRequest(\"Invalid unset value for %s\", columnsExpression);\n    }\n\n    private void validateElements(List<ByteBuffer> elements)\n    {\n        validate(elements);\n\n        List<ColumnMetadata> columns = columns();\n        for (int i = 0, m = columns.size(); i < m; i++)\n        {\n            ColumnMetadata column = columns.get(i);","sourceCodeStart":326,"sourceCodeEnd":362,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/restrictions/SimpleRestriction.java#L326-L362","documentation":"A restriction term bound to the UNSET sentinel (Term.UNSET_LIST) is rejected for list-typed restriction values. Cassandra distinguishes null from unset; this validate path disallows both for restriction lists, so validate throws an InvalidRequest.","triggerScenarios":"Executing a prepared statement where the list bound value was explicitly set to the driver's UNSET value rather than an actual list.","commonSituations":"Using unset-skip semantics on a restriction IN list where the API surface does not permit it; migrating code that relied on unset to omit restrictions.","solutions":["Bind an actual non-empty List instead of the UNSET sentinel","Remove the restriction clause from the CQL string when no value is intended","Guard client-side: if value is UNSET, build a different query string"],"exampleFix":"// before\nsession.execute(ps.bind(BoundStatement.UNSET));\n// after\nsession.execute(ps.bind(Arrays.asList(\"a\",\"b\")));","handlingStrategy":"validation","validationCode":"// guard before binding\nif (list == null || isUnset(list)) buildQueryWithoutPredicate(); else bindList(list);","typeGuard":"boolean isUnsetList(Object v) { return \"UNSET\".equals(v); }","tryCatchPattern":"catch (InvalidRequestException e) { if (e.getMessage().startsWith(\"Invalid unset value\")) rebuildQuery(); }","preventionTips":["Do not use UNSET sentinels on restriction lists; drop the predicate instead","Normalize unset values to 'absent' at the query-builder layer","Document that unset-skip applies to writes, not restriction terms"],"tags":["cql","prepared-statement","unset-value","query-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-17T15:17:12.973Z"}