{"record":{"id":"9fa4b86e3d5c4697","repo":"apache/cassandra","slug":"source-table-s-s-to-copy-indexes-from-to-s-s-h","errorCode":null,"errorMessage":"Source table %s.%s to copy indexes from to %s.%s has custom indexes. These indexes were not copied: %s","messagePattern":"Source table (.+?)\\.(.+?) to copy indexes from to (.+?)\\.(.+?) has custom indexes\\. These indexes were not copied: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/java/org/apache/cassandra/cql3/statements/schema/CopyTableStatement.java","lineNumber":362,"sourceCode":"                    //     then we directly replace the name of source table with the name of target table, and increment the number after idx to avoid index name conflicts.\n                    // (2) Index names that do not follow the above pattern are considered user-defined, so the index names are retained and increment the number after idx to avoid conflicts.\n                    if (indexMetadata.name.startsWith(sourceTableName + \"_\" + targetColumn.name + \"_idx\"))\n                    {\n                        String baseName = IndexMetadata.generateDefaultIndexName(targetTableName, targetColumn.name);\n                        indexName = targetKeyspaceMeta.findAvailableIndexName(baseName, indexesToCopy, targetKeyspaceMeta);\n                    }\n                    else\n                    {\n                        indexName = targetKeyspaceMeta.findAvailableIndexName(indexMetadata.name, indexesToCopy, targetKeyspaceMeta);\n                    }\n                    indexesToCopy.add(IndexMetadata.fromSchemaMetadata(indexName, indexMetadata.kind, indexMetadata.options));\n                }\n\n                if (!indexesToCopy.isEmpty())\n                    targetTableBuilder.indexes(Indexes.builder().add(indexesToCopy).build());\n\n                if (!customIndexes.isEmpty())\n                    ClientWarn.instance.warn(String.format(\"Source table %s.%s to copy indexes from to %s.%s has custom indexes. These indexes were not copied: %s\",\n                                                           sourceKeyspace,\n                                                           sourceTableName,\n                                                           targetKeyspace,\n                                                           targetTableName,\n                                                           customIndexes));\n            }\n        },\n        COMMENTS\n        {\n            @Override\n            public void copy(TableMetadata.Builder targetTableBuilder,\n                             String targetKeyspace,\n                             String targetTableName,\n                             TableMetadata sourceTableMeta,\n                             KeyspaceMetadata targetKeyspaceMeta)\n            {\n                if (!StringUtils.isEmpty(sourceTableMeta.params.comment))\n                    targetTableBuilder.comment(sourceTableMeta.params.comment);","sourceCodeStart":344,"sourceCodeEnd":380,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/cql3/statements/schema/CopyTableStatement.java#L344-L380","documentation":"CREATE TABLE ... WITH ... LIKE (copy table) replicates schema including indexes, but custom index implementations (Storage-attached / custom Index classes) cannot be copied to the new table. CopyTableStatement.copy warns the client listing the custom indexes that were skipped.","triggerScenarios":"Running `CREATE TABLE new_table WITH table LIKE source_table (or equivalent copy)` where the source table has custom/SAI indexes not supported for copying; the non-empty customIndexes set triggers the ClientWarn.","commonSituations":"Cloning tables that carry SAI or third-party custom indexes; schema-migration tooling copying table definitions; index type not available or not copyable on the target keyspace.","solutions":["Manually create the needed custom indexes on the new table with CREATE [CUSTOM] INDEX after the copy","If they are not needed on the copy, ignore the warning","Verify index definitions with DESC/RANGE QUERY of system_schema.indexes before copying"],"exampleFix":"// before\nCREATE TABLE ks.tbl_copy LIKE ks.tbl; // custom indexes skipped, warning only\n// after\nCREATE TABLE ks.tbl_copy LIKE ks.tbl;\nCREATE CUSTOM INDEX tbl_copy_idx ON ks.tbl_copy (col) USING 'StorageAttachedIndex';","handlingStrategy":"fallback","validationCode":"List<String> customIdx = session.execute(\"SELECT index_name FROM system_schema.indexes WHERE keyspace_name=? AND table_name=?\", ks, table)\n    .all().stream().map(r -> r.getString(\"index_name\")).collect(Collectors.toList());\n// after copy, recreate customIdx manually","typeGuard":null,"tryCatchPattern":null,"preventionTips":["List source-table indexes before copying schema","Script CREATE CUSTOM INDEX statements as part of copy workflows","Check index kind in system_schema.indexes to separate built-in from custom"],"tags":["cassandra","schema","indexes","client-warning"],"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"}