apache/cassandra · error · InvalidRequestException

Static columns are only useful (and thus allowed) if the tab

Error message

Static columns are only useful (and thus allowed) if the table has at least one clustering column

What it means

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.

Source

Thrown at src/java/org/apache/cassandra/cql3/statements/schema/AlterTableStatement.java:367

            AbstractType<?> type = column.type.prepare(keyspaceName, keyspace.types).getType();
            boolean isStatic = column.isStatic;
            ColumnMask mask = column.mask == null ? null : column.mask.prepare(keyspaceName, tableName, name, type, keyspace.userFunctions);
            ColumnConstraints columnConstraints = column.constraints == null ? ColumnConstraints.NO_OP : column.constraints.prepare(name);

            if (null != tableBuilder.getColumn(name)) {
                if (!ifColumnNotExists)
                    throw ire("Column with name '%s' already exists", name);
                return;
            }

            if (type.isCounter() && (table.params.transactionalMode.accordIsEnabled || table.params.transactionalMigrationFrom.migratingFromAccord()))
                throw ire(format(ACCORD_COUNTER_COLUMN_UNSUPPORTED, keyspaceName, tableName, table.params.transactionalMode, table.params.transactionalMigrationFrom));

            if (table.isCompactTable())
                throw ire("Cannot add new column to a COMPACT STORAGE table");

            if (isStatic && table.clusteringColumns().isEmpty())
                throw ire("Static columns are only useful (and thus allowed) if the table has at least one clustering column");

            // check for nested non-frozen UDTs or collections in a non-frozen UDT
            if (type.isUDT() && type.isMultiCell())
            {
                for (AbstractType<?> fieldType : ((UserType) type).fieldTypes())
                {
                    if (fieldType.isMultiCell())
                        throw ire("Non-frozen UDTs with nested non-frozen collections are not supported for column " + column.name);
                }
            }

            ColumnMetadata droppedColumn = table.getDroppedColumn(name.bytes);
            if (null != droppedColumn)
            {
                // After #8099, not safe to re-add columns of incompatible types - until *maybe* deser logic with dropped
                // columns is pushed deeper down the line. The latter would still be problematic in cases of schema races.
                if (!type.isSerializationCompatibleWith(droppedColumn.type))
                {

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Remove the STATIC keyword and add the column as a REGULAR column: ALTER TABLE t ADD col text;
  2. 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).
  3. Recreate the table with a composite primary key, e.g. PRIMARY KEY (pk, ck), then add the static column.
  4. If using a schema-management tool, disable automatic STATIC marking or ensure the target table model matches the source.

Example fix

// before
ALTER TABLE sensor_data ADD location text STATIC; -- sensor_data has PRIMARY KEY (device_id)
// after
ALTER TABLE sensor_data ADD location text;        -- regular column
-- or: recreate with PRIMARY KEY (device_id, ts) before using STATIC
Defensive patterns

Strategy: validation

Validate before calling

// before issuing ALTER TABLE ... ADD col type STATIC
TableMetadata table = Schema.instance.getTableMetadata(keyspace, tablename);
if (staticRequested && table.clusteringColumns().isEmpty())
    throw new IllegalArgumentException(
        "Table " + tablename + " has no clustering columns; STATIC column not allowed. Add column as REGULAR or recreate table with clustering key.");

Type guard

boolean staticAllowed(TableMetadata t) { return !t.clusteringColumns().isEmpty(); }

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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