apache/cassandra · error · InvalidRequestException

full() non-SAI indexes can only be created on frozen collect

Error message

full() non-SAI indexes can only be created on frozen collections

What it means

The full() index modifier is only meaningful for frozen collections, and for non-SAI index backends full() may only be used on frozen collections. Using full() on a non-collection column or on a multi-cell (non-frozen) collection with a legacy (non-SAI) index throws this error.

Source

Thrown at src/java/org/apache/cassandra/cql3/statements/schema/CreateIndexStatement.java:292

                throw  ire(UDTS_WITH_DURATIONS_NOT_SUPPORTED);

            throw ire(DURATIONS_NOT_SUPPORTED);
        }

        if (table.isCompactTable())
        {
            TableMetadata.CompactTableMetadata compactTable = (TableMetadata.CompactTableMetadata) table;
            if (column.isPrimaryKeyColumn())
                throw new InvalidRequestException(PRIMARY_KEY_IN_COMPACT_STORAGE);
            if (compactTable.compactValueColumn.equals(column))
                throw new InvalidRequestException(COMPACT_COLUMN_IN_COMPACT_STORAGE);
        }

        if (column.isPartitionKey() && table.partitionKeyColumns().size() == 1)
            throw ire(ONLY_PARTITION_KEY, column);

        if (target.type == Type.FULL && isNonSAIIndex && (!baseType.isCollection() || column.type.isMultiCell()))
            throw ire(FULL_ON_FROZEN_COLLECTIONS);

        if (!baseType.isCollection() && target.type != Type.SIMPLE)
            throw ire(NON_COLLECTION_SIMPLE_INDEX, target.type, column);

        // Frozen collections are only supported with SAI indexes.
        if (isNonSAIIndex && baseType.isCollection() && !column.type.isMultiCell())
        {
            if (target.type == Type.VALUES || target.type == Type.KEYS || target.type == Type.KEYS_AND_VALUES)
            {
                throw ire(CREATE_ON_FROZEN_COLUMN, target.type.toString(), column.name, column.name);
            }
        }

        if (!(baseType instanceof MapType) && (target.type == Type.KEYS || target.type == Type.KEYS_AND_VALUES ))
            throw ire(CREATE_WITH_NON_MAP_TYPE, target.type, column);

        // Can't query map[key]=value on clustering key columns, so ENTRIES index would be not queryable.
        if (column.isClusteringColumn() && baseType instanceof MapType && !column.type.isMultiCell()

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Remove the full() modifier for non-collection columns: CREATE INDEX ON t (col).
  2. For collections, declare the column frozen (frozen<list<int>>) if full-indexing is required, then use full(col).
  3. Switch to SAI (Storage-Attached Indexing) if on a version that supports it, which handles frozen collections differently.

Example fix

// before
CREATE INDEX ON t (full(tags)); // tags: list<text> (multi-cell)
// after
ALTER TABLE t ALTER tags TYPE frozen<list<text>>; -- or redefine table
CREATE INDEX ON t (full(tags));
Defensive patterns

Strategy: validation

Validate before calling

if (target.type === 'FULL' && !isSaiIndex && (!baseType.isCollection() || column.type.isMultiCell())) throw new Error('full() requires a frozen collection for non-SAI indexes');

Type guard

const fullAllowed = (t, sai) => sai || (t.isCollection() && !t.isMultiCell());

Try / catch

try { session.execute(ddl); } catch (e) { if (/can only be created on frozen collections/.test(e.message)) { /* drop full() or freeze the collection */ } else throw e; }

Prevention

When it happens

Trigger: `CREATE INDEX ON t (full(col))` where col is not a collection (e.g. an int or text column), or where col is a multi-cell (non-frozen) list/set/map, with a non-SAI index implementation (legacy SecondaryIndex, SASI, most CUSTOM backends).

Common situations: Copy-pasting full() from SAI examples onto legacy index DDL; applying full() to every column when adding indexes broadly; confusion between frozen and non-frozen collection declarations.

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