apache/cassandra · error · InvalidRequestException

Invalid unset value for list index

Error message

Invalid unset value for list index

What it means

Thrown when the index of a list element assignment is left UNSET (the driver's explicit 'unset' marker, distinct from null). Indexed list writes require a concrete index; unset would make the operation nondeterministic, so it is rejected.

Solutions

  1. Always bind an actual integer index for l[?] operations — unset is not allowed
  2. Construct a different statement (whole-list assignment or removal) when the index is not known
  3. Restrict generic unset-based bind helpers to non-indexed operations

Example fix

// before
ps.setBytesUnsafe(0, unset); // unset index
// after
if (index == null) throw new IllegalArgumentException("list index required");
ps.setInt(0, index);
Defensive patterns

Strategy: validation

Validate before calling

if (index == null || isUnset(index)) throw new IllegalArgumentException("list index must be bound, not unset");

Try / catch

try { session.execute(stmt); } catch (InvalidQueryException e) { if (e.getMessage().contains("Invalid unset value for list index")) { /* bind a real index */ } else throw e; }

Prevention

When it happens

Trigger: `UPDATE t SET l[?] = ?` where the index parameter is bound to the driver's unset value (e.g. unsetValue() in the Java driver).

Common situations: Reusing a generic 'update all fields or leave unset' binding helper for indexed list operations; templated batch code that marks all optional params unset.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/cql3/terms/Lists.java:366

            super.collectMarkerSpecification(boundNames, owner);
            idx.collectMarkerSpecification(boundNames, owner);
        }

        public void execute(DecoratedKey partitionKey, RowUpdateBuilder builder) throws InvalidRequestException
        {
            // we should not get here for frozen lists
            assert column.type.isMultiCell() : "Attempted to set an individual element on a frozen list";

            Guardrails.readBeforeWriteListOperationsEnabled
            .ensureEnabled("Setting of list items by index requiring read before write", builder.clientState);

            ByteBuffer index = idx.bindAndGet(builder);
            ByteBuffer value = t.bindAndGet(builder);

            if (index == null)
                throw new InvalidRequestException("Invalid null value for list index");
            if (index == ByteBufferUtil.UNSET_BYTE_BUFFER)
                throw new InvalidRequestException("Invalid unset value for list index");

            Row existingRow = builder.getPrefetchedRow(partitionKey, builder.currentClustering());
            int existingSize = existingSize(existingRow, column);
            int idx = ByteBufferUtil.toInt(index);
            if (existingSize == 0)
                throw new InvalidRequestException("Attempted to set an element on a list which is null");
            if (idx < 0 || idx >= existingSize)
                throw new InvalidRequestException(String.format("List index %d out of bound, list has size %d", idx, existingSize));

            CellPath elementPath = existingRow.getComplexColumnData(column).getCellByIndex(idx).path();
            if (value == null)
                builder.addTombstone(column, elementPath);
            else if (value != ByteBufferUtil.UNSET_BYTE_BUFFER)
                builder.addCell(column, elementPath, value);
        }
    }

    public static class Appender extends Operation

View on GitHub (pinned to 88fd0f6a0e)