{"record":{"id":"868dfcc1432d2d1c","repo":"apache/cassandra","slug":"invalid-non-frozen-collection-type-s-for-primar","errorCode":null,"errorMessage":"Invalid non-frozen collection type '%s' for PRIMARY KEY column '%s'","messagePattern":"Invalid non-frozen collection type '(.+?)' for PRIMARY KEY column '(.+?)'","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/statements/schema/CreateViewStatement.java","lineNumber":256,"sourceCode":"            throw ire(\"Must provide at least one partition key column for materialized view '%s'\", viewName);\n\n        HashSet<ColumnIdentifier> primaryKeyColumns = new HashSet<>();\n\n        concat(partitionKeyColumns, clusteringColumns).forEach(name ->\n        {\n            ColumnMetadata column = table.getColumn(name);\n            if (null == column || !selectedColumns.contains(name))\n                throw ire(\"Unknown column '%s' referenced in PRIMARY KEY for materialized view '%s'\", name, viewName);\n\n            if (!primaryKeyColumns.add(name))\n                throw ire(\"Duplicate column '%s' in PRIMARY KEY clause for materialized view '%s'\", name, viewName);\n\n            AbstractType<?> type = column.type;\n\n            if (type.isMultiCell())\n            {\n                if (type.isCollection())\n                    throw ire(\"Invalid non-frozen collection type '%s' for PRIMARY KEY column '%s'\", type, name);\n                else\n                    throw ire(\"Invalid non-frozen user-defined type '%s' for PRIMARY KEY column '%s'\", type, name);\n            }\n\n            if (type.isCounter())\n                throw ire(\"counter type is not supported for PRIMARY KEY column '%s'\", name);\n\n            if (type.referencesDuration())\n                throw ire(\"duration type is not supported for PRIMARY KEY column '%s'\", name);\n        });\n\n        // If we give a clustering order, we must explicitly do so for all aliases and in the order of the PK\n        if (!clusteringOrder.isEmpty() && !clusteringColumns.equals(new ArrayList<>(clusteringOrder.keySet())))\n            throw ire(\"Clustering key columns must exactly match columns in CLUSTERING ORDER BY directive\");\n\n        /*\n         * We need to include all of the primary key columns from the base table in order to make sure that we do not\n         * overwrite values in the view. We cannot support \"collapsing\" the base table into a smaller number of rows in","sourceCodeStart":238,"sourceCodeEnd":274,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/statements/schema/CreateViewStatement.java#L238-L274","documentation":"Primary key columns of a materialized view must be single-cell values. Non-frozen collections and non-frozen user-defined types are multi-cell and cannot serve as view keys; counter columns are likewise banned.","triggerScenarios":"CREATE MATERIALIZED VIEW whose PRIMARY KEY includes a non-frozen list/map/set or non-frozen UDT, e.g. PRIMARY KEY (pk, tags) where tags is a set<text>.","commonSituations":"Using a collection to group rows into a view key; schema drift where a column became a collection later; forgetting the frozen<> keyword when the table was created.","solutions":["Wrap the collection/UDT in frozen<>, e.g. frozen<set<text>> (requires recreating the base table or migrating data, since types cannot be altered in place)","Choose a scalar column as the view key and add the collection as a non-key projected column","Denormalize collection elements into individual rows/columns in a base table maintained by the application"],"exampleFix":"// before\nCREATE TABLE base (pk text, tags set<text>, v int, PRIMARY KEY (pk));\nCREATE MATERIALIZED VIEW mv AS SELECT pk, tags, v FROM base WHERE pk IS NOT NULL AND tags IS NOT NULL PRIMARY KEY (pk, tags);\n// after\nCREATE TABLE base2 (pk text, tags frozen<set<text>>, v int, PRIMARY KEY (pk));\nCREATE MATERIALIZED VIEW mv AS SELECT pk, tags, v FROM base2 WHERE pk IS NOT NULL AND tags IS NOT NULL PRIMARY KEY (pk, tags);","handlingStrategy":"validation","validationCode":"for (String c : primaryKeyCols) { AbstractType<?> t = baseTable.getColumn(c).type; if (t.isMultiCell() && t.isCollection()) throw new IllegalArgumentException(\"Frozen collection required for key: \" + c); }","typeGuard":"boolean isKeySafe(AbstractType<?> t) { return !t.isMultiCell() || (t instanceof FrozenType); }","tryCatchPattern":"try { session.execute(createMvStmt); } catch (InvalidQueryException e) { if (e.getMessage().contains(\"non-frozen collection\")) { /* use frozen<> or pick another key column */ } }","preventionTips":["Prefer frozen<> collections when a collection must participate in a key","Design base-table keys with scalar, single-cell types"],"tags":["cql","materialized-view","primary-key","frozen-collection"],"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"}