{"record":{"id":"026b33427cad48f9","repo":"apache/cassandra","slug":"cannot-add-new-column-to-a-compact-storage-table","errorCode":null,"errorMessage":"Cannot add new column to a COMPACT STORAGE table","messagePattern":"Cannot add new column to a COMPACT STORAGE table","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/statements/schema/AlterTableStatement.java","lineNumber":364,"sourceCode":"                               Views.Builder viewsBuilder)\n        {\n            ColumnIdentifier name = column.name;\n            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","sourceCodeStart":346,"sourceCodeEnd":382,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/statements/schema/AlterTableStatement.java#L346-L382","documentation":"Tables created WITH COMPACT STORAGE use the legacy Thrift-compatible storage format with a fixed column set; adding new columns via ALTER TABLE is rejected. Compact tables cannot gain new non-primary columns after creation.","triggerScenarios":"ALTER TABLE ... ADD on a table where table.isCompactTable() is true — i.e. tables created with WITH COMPACT STORAGE, typically legacy tables migrated from Thrift","commonSituations":"Operating on legacy Thrift-era tables; applying generic schema migration scripts (written for regular tables) against compact-storage tables; attempting to extend an old data model in place.","solutions":["Migrate the table to a regular (non-compact) schema: create a new table without COMPACT STORAGE and copy data across","If the legacy schema must stay, add needed data via the existing sparse column encoding or a companion table","Check table params: SELECT * FROM system_schema.tables WHERE keyspace_name=? AND table_name=? (compact_storage flag) before scripting DDL"],"exampleFix":"// before\nsession.execute(\"ALTER TABLE my_app.legacy_metrics ADD description text\");\n// after\nsession.execute(\"CREATE TABLE my_app.metrics (id uuid PRIMARY KEY, value blob, description text)\");\n// then copy data from legacy_metrics into metrics and drop the compact table","handlingStrategy":"validation","validationCode":"Row r = session.execute(\"SELECT * FROM system_schema.tables WHERE keyspace_name=? AND table_name=?\", ks, table).one();\nif (r != null && r.getBoolean(\"compact_storage\"))\n    throw new IllegalStateException(\"Cannot ADD columns to a COMPACT STORAGE table\");","typeGuard":null,"tryCatchPattern":"try {\n    session.execute(alter);\n} catch (InvalidRequestException e) {\n    if (e.getMessage().contains(\"COMPACT STORAGE\"))\n        log.error(\"Legacy compact table requires migration before schema change\");\n    else throw e;\n}","preventionTips":["Detect COMPACT STORAGE tables during migration planning","Plan full re-creation + data copy for extending legacy tables","Avoid creating new tables WITH COMPACT STORAGE"],"tags":["cassandra","cql","ddl","compact-storage","legacy"],"backgroundTag":"unsupported-operation","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"}