{"record":{"id":"ed4025f3d090ad98","repo":"apache/cassandra","slug":"cannot-s-column-s-because-it-has-dependent-secon","errorCode":null,"errorMessage":"Cannot %s column %s because it has dependent secondary indexes (%s)","messagePattern":"Cannot (.+?) column (.+?) because it has dependent secondary indexes \\((.+?)\\)","errorType":"validation","errorClass":"InvalidRequestException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/cql3/statements/schema/AlterTableStatement.java","lineNumber":452,"sourceCode":"        {\n            Optional<Pair<ColumnMetadata, IndexTarget.Type>> target = TargetParser.tryParse(table, index);\n            if (target.isEmpty())\n            {\n                // The target column(s) of this index is not trivially discernible from its metadata.\n                // This implies an external custom index implementation and without instantiating the\n                // index itself we cannot be sure that the column metadata is safe to modify.\n                dependentIndexes.add(index.name);\n            }\n            else if (target.get().left.equals(column))\n            {\n                // The index metadata declares an explicit dependency on the column being modified, so\n                // the mutation must be rejected.\n                dependentIndexes.add(index.name);\n            }\n        }\n        if (!dependentIndexes.isEmpty())\n        {\n            throw ire(\"Cannot %s column %s because it has dependent secondary indexes (%s)\",\n                      isRename ? \"rename\" : \"drop\",\n                      colId,\n                      join(\", \", dependentIndexes));\n        }\n    }\n\n    /**\n     * {@code ALTER TABLE [IF EXISTS] <table> DROP [IF EXISTS] <column>}\n     * {@code ALTER TABLE [IF EXISTS] <table> DROP [IF EXISTS] ( <column>, <column1>, ... <columnn>)}\n     */\n    // TODO: swap UDT refs with expanded tuples on drop\n    private static class DropColumns extends AlterTableStatement\n    {\n        private final Set<ColumnIdentifier> removedColumns;\n        private final boolean ifColumnExists;\n        private final Long timestamp;\n\n        private DropColumns(String keyspaceName, String tableName, Set<ColumnIdentifier> removedColumns, boolean ifTableExists, boolean ifColumnExists, Long timestamp)","sourceCodeStart":434,"sourceCodeEnd":470,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/statements/schema/AlterTableStatement.java#L434-L470","documentation":"This InvalidRequestException is thrown when an ALTER TABLE DROP (or RENAME) targets a column that has secondary indexes defined on it. Cassandra refuses the schema change because dropping/renaming the column would leave the index metadata pointing at a non-existent or renamed column. The message lists every dependent index so the developer knows exactly which indexes to drop first.","triggerScenarios":"Executing `ALTER TABLE ... DROP column` or `ALTER TABLE ... RENAME column` on a column that is the target of a secondary index (CREATE INDEX). Also triggered when a custom index implementation's target column cannot be discerned from metadata (TargetParser.tryParse returns empty), which is treated as a dependency conservatively.","commonSituations":"Developers added a secondary index during prototyping and later try to clean up the schema by dropping the indexed column; schema migration scripts that drop columns without first checking system_schema.indexes; tables using custom index implementations (e.g. Storage-Attached Indexes or third-party indexes) where all column changes are rejected.","solutions":["Drop the dependent secondary index first: `DROP INDEX <keyspace>.<index_name>`, then re-run the ALTER TABLE DROP/RENAME.","If the index is still needed, drop/re-add it around the change: DROP INDEX, ALTER TABLE DROP COLUMN, then re-create the index on a suitable column.","If using a custom index, consult its documentation; you may need to remove the custom index before modifying any column.","Query system_schema.indexes (or DESCRIBE TABLE) beforehand to identify indexes on the target column."],"exampleFix":"// before\nALTER TABLE users DROP email; -- fails: dependent index users_email_idx\n// after\nDROP INDEX users_email_idx;\nALTER TABLE users DROP email;","handlingStrategy":"validation","validationCode":"// CQL pre-check before ALTER TABLE DROP/RENAME\nSELECT index_name, options FROM system_schema.indexes\nWHERE keyspace_name = 'ks' AND table_name = 'tbl';\n// If any row targets the column (or is a custom index), drop the index first.","typeGuard":null,"tryCatchPattern":"// Driver (java)\ntry {\n    session.execute(\"ALTER TABLE ks.tbl DROP col\");\n} catch (com.datastax.oss.driver.api.core.servererrors.InvalidQueryException e) {\n    if (e.getMessage().contains(\"dependent secondary indexes\")) {\n        // parse index names from message and DROP INDEX before retrying\n    } else throw e;\n}","preventionTips":["Check system_schema.indexes for the column before any DROP/RENAME migration.","Make migrations idempotent with IF EXISTS and explicit DROP INDEX steps.","Avoid secondary indexes in favor of denormalized tables/query tables where possible.","Treat any custom index as blocking all column modifications."],"tags":["cql","schema","secondary-index","alter-table"],"backgroundTag":"unsupported-operation","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"}