apache/cassandra · error · InvalidRequestException

Invalid unset value for

Error message

Invalid unset value for %s

What it means

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.

Solutions

  1. Bind an actual non-empty List instead of the UNSET sentinel
  2. Remove the restriction clause from the CQL string when no value is intended
  3. Guard client-side: if value is UNSET, build a different query string

Example fix

// before
session.execute(ps.bind(BoundStatement.UNSET));
// after
session.execute(ps.bind(Arrays.asList("a","b")));
Defensive patterns

Strategy: validation

Validate before calling

// guard before binding
if (list == null || isUnset(list)) buildQueryWithoutPredicate(); else bindList(list);

Type guard

boolean isUnsetList(Object v) { return "UNSET".equals(v); }

Try / catch

catch (InvalidRequestException e) { if (e.getMessage().startsWith("Invalid unset value")) rebuildQuery(); }

Prevention

When it happens

Trigger: Executing a prepared statement where the list bound value was explicitly set to the driver's UNSET value rather than an actual list.

Common situations: 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.

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/5d93ad18347f632a. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/cql3/restrictions/SimpleRestriction.java:344

        ByteBuffer buffer = values.bindAndGetSingleTermValue(context);
        validate(buffer);
        return buffer;
    }

    private List<List<ByteBuffer>> bindAndGetElements(FunctionContext context)
    {
        List<List<ByteBuffer>> elementsList = values.bindAndGetElements(context);
        validate(elementsList);
        elementsList.forEach(this::validateElements);
        return elementsList;
    }

    private void validate(List<?> list)
    {
        if (list == null)
            throw invalidRequest("Invalid null value for %s", columnsExpression);
        if (list == Term.UNSET_LIST)
            throw invalidRequest("Invalid unset value for %s", columnsExpression);
    }

    private void validate(ByteBuffer buffer)
    {
        if (buffer == null)
            throw invalidRequest("Invalid null value for %s", columnsExpression);
        if (buffer == ByteBufferUtil.UNSET_BYTE_BUFFER)
            throw invalidRequest("Invalid unset value for %s", columnsExpression);
    }

    private void validateElements(List<ByteBuffer> elements)
    {
        validate(elements);

        List<ColumnMetadata> columns = columns();
        for (int i = 0, m = columns.size(); i < m; i++)
        {
            ColumnMetadata column = columns.get(i);

View on GitHub (pinned to 88fd0f6a0e)