{"record":{"id":"1b1c1a008ccaa9f9","repo":"apache/cassandra","slug":"static-columns-are-only-useful-and-thus-allowed","errorCode":null,"errorMessage":"Static columns are only useful (and thus allowed) if the table has at least one clustering column","messagePattern":"Static columns are only useful \\(and thus allowed\\) if the table has at least one clustering column","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/statements/schema/AlterTableStatement.java","lineNumber":367,"sourceCode":"            AbstractType<?> type = column.type.prepare(keyspaceName, keyspace.types).getType();\n            boolean isStatic = column.isStatic;\n            ColumnMask mask = column.mask == null ? null : column.mask.prepare(keyspaceName, tableName, name, type, keyspace.userFunctions);\n            ColumnConstraints columnConstraints = column.constraints == null ? ColumnConstraints.NO_OP : column.constraints.prepare(name);\n\n            if (null != tableBuilder.getColumn(name)) {\n                if (!ifColumnNotExists)\n                    throw ire(\"Column with name '%s' already exists\", name);\n                return;\n            }\n\n            if (type.isCounter() && (table.params.transactionalMode.accordIsEnabled || table.params.transactionalMigrationFrom.migratingFromAccord()))\n                throw ire(format(ACCORD_COUNTER_COLUMN_UNSUPPORTED, keyspaceName, tableName, table.params.transactionalMode, table.params.transactionalMigrationFrom));\n\n            if (table.isCompactTable())\n                throw ire(\"Cannot add new column to a COMPACT STORAGE table\");\n\n            if (isStatic && table.clusteringColumns().isEmpty())\n                throw ire(\"Static columns are only useful (and thus allowed) if the table has at least one clustering column\");\n\n            // check for nested non-frozen UDTs or collections in a non-frozen UDT\n            if (type.isUDT() && type.isMultiCell())\n            {\n                for (AbstractType<?> fieldType : ((UserType) type).fieldTypes())\n                {\n                    if (fieldType.isMultiCell())\n                        throw ire(\"Non-frozen UDTs with nested non-frozen collections are not supported for column \" + column.name);\n                }\n            }\n\n            ColumnMetadata droppedColumn = table.getDroppedColumn(name.bytes);\n            if (null != droppedColumn)\n            {\n                // After #8099, not safe to re-add columns of incompatible types - until *maybe* deser logic with dropped\n                // columns is pushed deeper down the line. The latter would still be problematic in cases of schema races.\n                if (!type.isSerializationCompatibleWith(droppedColumn.type))\n                {","sourceCodeStart":349,"sourceCodeEnd":385,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/statements/schema/AlterTableStatement.java#L349-L385","documentation":"ALTER TABLE ... ADD with a STATIC column is rejected when the table has no clustering columns. Static columns only make sense in tables with clustering columns, since their value is shared across all rows sharing the same partition, and with no clustering columns there is exactly one row per partition, making a static column pointless. Cassandra throws this InvalidRequest at schema-alteration time rather than allowing a useless layout.","triggerScenarios":"Executing ALTER TABLE <table> ADD <col> <type> STATIC (or the ADD COLUMN API with isStatic=true) via CQL, cqlsh, or a driver schema statement on a table created without any clustering columns (e.g. CREATE TABLE ... (pk PRIMARY KEY) with no CLUSTERING ORDER).","commonSituations":"Migrating a schema designed for a clustered table onto a simple primary-key table; tools generating STATIC columns unconditionally; hand-writing DDL against a table the developer assumed had clustering columns; scripted schema sync tools copying static-column definitions between tables.","solutions":["Remove the STATIC keyword and add the column as a REGULAR column: ALTER TABLE t ADD col text;","Add at least one clustering column to the table before declaring static columns (may require creating a new table, since clustering columns cannot be added via ALTER TABLE).","Recreate the table with a composite primary key, e.g. PRIMARY KEY (pk, ck), then add the static column.","If using a schema-management tool, disable automatic STATIC marking or ensure the target table model matches the source."],"exampleFix":"// before\nALTER TABLE sensor_data ADD location text STATIC; -- sensor_data has PRIMARY KEY (device_id)\n// after\nALTER TABLE sensor_data ADD location text;        -- regular column\n-- or: recreate with PRIMARY KEY (device_id, ts) before using STATIC","handlingStrategy":"validation","validationCode":"// before issuing ALTER TABLE ... ADD col type STATIC\nTableMetadata table = Schema.instance.getTableMetadata(keyspace, tablename);\nif (staticRequested && table.clusteringColumns().isEmpty())\n    throw new IllegalArgumentException(\n        \"Table \" + tablename + \" has no clustering columns; STATIC column not allowed. Add column as REGULAR or recreate table with clustering key.\");","typeGuard":"boolean staticAllowed(TableMetadata t) { return !t.clusteringColumns().isEmpty(); }","tryCatchPattern":null,"preventionTips":["Only mark columns STATIC when the primary key is composite (partition key + clustering columns).","Never let schema generators emit STATIC unconditionally; derive it from the table's clustering columns.","Verify table metadata (system_schema.columns, kind='clustering') before generating DDL.","Prefer a regular column when a table has one row per partition."],"tags":["cql","schema","alter-table","static-column"],"backgroundTag":"schema-validation-failed","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}