apache/cassandra · warning

Source table . to copy indexes from to . has custom…

Error message

Source table %s.%s to copy indexes from to %s.%s has custom indexes. These indexes were not copied: %s

What it means

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.

Solutions

  1. Manually create the needed custom indexes on the new table with CREATE [CUSTOM] INDEX after the copy
  2. If they are not needed on the copy, ignore the warning
  3. Verify index definitions with DESC/RANGE QUERY of system_schema.indexes before copying

Example fix

// before
CREATE TABLE ks.tbl_copy LIKE ks.tbl; // custom indexes skipped, warning only
// after
CREATE TABLE ks.tbl_copy LIKE ks.tbl;
CREATE CUSTOM INDEX tbl_copy_idx ON ks.tbl_copy (col) USING 'StorageAttachedIndex';
Defensive patterns

Strategy: fallback

Validate before calling

List<String> customIdx = session.execute("SELECT index_name FROM system_schema.indexes WHERE keyspace_name=? AND table_name=?", ks, table)
    .all().stream().map(r -> r.getString("index_name")).collect(Collectors.toList());
// after copy, recreate customIdx manually

Prevention

When it happens

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

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

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/cql3/statements/schema/CopyTableStatement.java:362

                    //     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.
                    // (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.
                    if (indexMetadata.name.startsWith(sourceTableName + "_" + targetColumn.name + "_idx"))
                    {
                        String baseName = IndexMetadata.generateDefaultIndexName(targetTableName, targetColumn.name);
                        indexName = targetKeyspaceMeta.findAvailableIndexName(baseName, indexesToCopy, targetKeyspaceMeta);
                    }
                    else
                    {
                        indexName = targetKeyspaceMeta.findAvailableIndexName(indexMetadata.name, indexesToCopy, targetKeyspaceMeta);
                    }
                    indexesToCopy.add(IndexMetadata.fromSchemaMetadata(indexName, indexMetadata.kind, indexMetadata.options));
                }

                if (!indexesToCopy.isEmpty())
                    targetTableBuilder.indexes(Indexes.builder().add(indexesToCopy).build());

                if (!customIndexes.isEmpty())
                    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",
                                                           sourceKeyspace,
                                                           sourceTableName,
                                                           targetKeyspace,
                                                           targetTableName,
                                                           customIndexes));
            }
        },
        COMMENTS
        {
            @Override
            public void copy(TableMetadata.Builder targetTableBuilder,
                             String targetKeyspace,
                             String targetTableName,
                             TableMetadata sourceTableMeta,
                             KeyspaceMetadata targetKeyspaceMeta)
            {
                if (!StringUtils.isEmpty(sourceTableMeta.params.comment))
                    targetTableBuilder.comment(sourceTableMeta.params.comment);

View on GitHub (pinned to 88fd0f6a0e)