apache/cassandra · error · InvalidRequestException

Secondary indexes are not supported on transiently…

Error message

Secondary indexes are not supported on transiently replicated keyspaces

What it means

Secondary indexes (including custom ones) cannot be created on keyspaces whose replication strategy uses transient replication ( AnyaReplication/network topology with transient replicas). Transient replicas store no full data copy, so index maintenance and read repair semantics are incompatible. The statement checks `keyspace.replicationStrategy.hasTransientReplicas()` and throws InvalidRequestException.

Solutions

  1. Remove transient replication from the keyspace (`ALTER KEYSPACE ... WITH replication = {...}` using full replicas) and run a full repair, then create the index.
  2. Create the index in a keyspace that does not use transient replication.
  3. Use a different query strategy (e.g. denormalized table or SAI if applicable per version) that is compatible with transient replication.

Example fix

-- before
cqlsh> CREATE INDEX ON myks.mytable (col); -- keyspace has transient replicas

-- after
ALTER KEYSPACE myks WITH replication = {'class':'NetworkTopologyStrategy','dc1':3};
-- nodetool repair -full myks
CREATE INDEX ON myks.mytable (col);
Defensive patterns

Strategy: validation

Validate before calling

KeyspaceMetadata ks = session.getCluster().getMetadata().getKeyspace("myks");
if (ks != null && ks.getReplication().containsKey("txnr") /* transient replicas */)
    throw new IllegalStateException("cannot create 2i on transiently replicated keyspace");

Try / catch

try { session.execute(createIndex); }
catch (InvalidQueryException e) {
  if (e.getMessage().contains("transiently replicated"))
      throw new IllegalStateException("ALTER KEYSPACE to full replicas + repair before indexing", e);
  throw e;
}

Prevention

When it happens

Trigger: `CREATE [CUSTOM] INDEX ...` targeting a table whose keyspace was created with a replication factor like `txnr`/transient replicas (e.g. `NetworkTopologyStrategy` with a datacenter RF like `3/1`).

Common situations: Using transient replication for cost savings and then trying to add a 2i for ad-hoc queries; tooling that auto-creates indexes without checking keyspace replication settings.

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/5bda83018fc62c5a. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/cql3/statements/schema/CreateIndexStatement.java:178

        if (null == table)
            throw ire(TABLE_DOES_NOT_EXIST, tableName);

        if (null != indexName && keyspace.hasIndex(indexName))
        {
            if (ifNotExists)
                return schema;

            throw ire(INDEX_ALREADY_EXISTS, indexName);
        }

        if (table.isCounter())
            throw ire(COUNTER_TABLES_NOT_SUPPORTED);

        if (table.isView())
            throw ire(MATERIALIZED_VIEWS_NOT_SUPPORTED);

        if (keyspace.replicationStrategy.hasTransientReplicas())
            throw new InvalidRequestException(TRANSIENTLY_REPLICATED_KEYSPACE_NOT_SUPPORTED);

        // guardrails to limit number of secondary indexes per table.
        Guardrails.secondaryIndexesPerTable.guard(table.indexes.size() + 1,
                                                  Strings.isNullOrEmpty(indexName)
                                                  ? String.format("on table %s", table.name)
                                                  : String.format("%s on table %s", indexName, table.name),
                                                  false,
                                                  state);

        List<IndexTarget> indexTargets = Lists.newArrayList(transform(rawIndexTargets, t -> t.prepare(table)));

        if (indexTargets.isEmpty() && !attrs.isCustom)
            throw ire(CUSTOM_CREATE_WITHOUT_COLUMN);

        if (indexTargets.size() > 1)
        {
            if (!attrs.isCustom)
                throw ire(CUSTOM_MULTIPLE_COLUMNS);

View on GitHub (pinned to 88fd0f6a0e)