apache/cassandra · error · InvalidRequestException

Invalid non-frozen collection type

Error message

Invalid non-frozen collection type %s for PRIMARY KEY column '%s'

What it means

CreateTableStatement.builder validation: a PRIMARY KEY column was declared as a non-frozen collection; multi-cell collections cannot be part of the primary key, so the type must be frozen or removed from the key.

Solutions

  1. Freeze the collection: use `frozen<set<int>>` as the column type
  2. Use a scalar or tuple type for the key column instead
  3. Model the data differently (e.g. denormalize the collection element into the key)

Example fix

// before
CREATE TABLE t (k set<int>, v int, PRIMARY KEY (k));
// after
CREATE TABLE t (k frozen<set<int>>, v int, PRIMARY KEY (k));
Defensive patterns

Strategy: validation

Validate before calling

if (keyColumnType.isCollection() && keyColumnType.isMultiCell()) throw new IllegalArgumentException("freeze collection before using as PRIMARY KEY column: frozen<...>");

Try / catch

try { session.execute(ddl); } catch (InvalidRequestException e) { if (e.getMessage().contains("Invalid non-frozen collection type")) { /* rewrite as frozen<type> */ } else throw e; }

Prevention

When it happens

Trigger: `CREATE TABLE t (k set<int>, PRIMARY KEY (k))` or `PRIMARY KEY (...)` referencing a list/map column without frozen<>.

Common situations: Trying to index or key rows by collection values; porting relational designs that used composite keys into CQL collections.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/cql3/statements/schema/CreateTableStatement.java:306

         * Deal with PRIMARY KEY columns
         */

        HashSet<ColumnIdentifier> primaryKeyColumns = new HashSet<>();
        concat(partitionKeyColumns, clusteringColumns).forEach(column ->
        {
            ColumnProperties properties = columns.get(column);
            if (null == properties)
                throw ire("Unknown column '%s' referenced in PRIMARY KEY for table '%s'", column, tableName);

            if (!primaryKeyColumns.add(column))
                throw ire("Duplicate column '%s' in PRIMARY KEY clause for table '%s'", column, tableName);

            AbstractType<?> type = properties.type;
            if (type.isMultiCell())
            {
                CQL3Type cqlType = properties.cqlType;
                if (type.isCollection())
                    throw ire("Invalid non-frozen collection type %s for PRIMARY KEY column '%s'", cqlType, column);
                else
                    throw ire("Invalid non-frozen user-defined type %s for PRIMARY KEY column '%s'", cqlType, column);
            }

            if (type.isCounter())
                throw ire("counter type is not supported for PRIMARY KEY column '%s'", column);

            if (type.referencesDuration())
                throw ire("duration type is not supported for PRIMARY KEY column '%s'", column);

            if (staticColumns.contains(column))
                throw ire("Static column '%s' cannot be part of the PRIMARY KEY", column);
        });

        List<ColumnProperties> partitionKeyColumnProperties = new ArrayList<>();
        List<ColumnProperties> clusteringColumnProperties = new ArrayList<>();

        partitionKeyColumns.forEach(column ->

View on GitHub (pinned to 88fd0f6a0e)