apache/cassandra · error · InvalidRequestException

Secondary indexes on counter tables aren't supported

Error message

Secondary indexes on counter tables aren't supported

What it means

CREATE INDEX guard rejecting secondary indexes on tables containing counter columns. Counter increments cannot be indexed, so index creation on a counter table is rejected at schema-change application time.

Solutions

  1. Do not index counter tables; query by key or maintain a separate table for lookup patterns.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at src/java/org/apache/cassandra/cql3/statements/schema/CreateIndexStatement.java:172 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

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

        Keyspaces schema = metadata.schema.getKeyspaces();
        KeyspaceMetadata keyspace = schema.getNullable(keyspaceName);
        if (null == keyspace)
            throw ire(KEYSPACE_DOES_NOT_EXIST, keyspaceName);

        TableMetadata table = keyspace.getTableOrViewNullable(tableName);
        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)

View on GitHub (pinned to 88fd0f6a0e)