apache/cassandra · error · InvalidRequestException
Must specify index implementation via USING
Error message
Must specify index implementation via USING
What it means
When no default secondary index implementation is configured (default_secondary_index disabled), a CREATE INDEX without an explicit `USING <implementation>` cannot pick an implementation and is rejected. Cassandra requires the operator to state which 2i engine (e.g. legacy LocalTableSecondaryIndex or SAI) to use.
Source
Thrown at src/java/org/apache/cassandra/cql3/statements/schema/CreateIndexStatement.java:395
{
String keyspaceName = tableName.hasKeyspace()
? tableName.getKeyspace()
: indexName.hasKeyspace() ? indexName.getKeyspace() : state.getKeyspace();
if (tableName.hasKeyspace() && !keyspaceName.equals(tableName.getKeyspace()))
throw ire(KEYSPACE_DOES_NOT_MATCH_TABLE, keyspaceName, tableName);
if (indexName.hasKeyspace() && !keyspaceName.equals(indexName.getKeyspace()))
throw ire(KEYSPACE_DOES_NOT_MATCH_INDEX, keyspaceName, tableName);
// Set the configured default 2i implementation if one isn't specified with USING:
if (attrs.customClass == null)
{
if (DatabaseDescriptor.getDefaultSecondaryIndexEnabled())
attrs.customClass = DatabaseDescriptor.getDefaultSecondaryIndex();
else
// However, operators may require an implementation be specified
throw ire(MUST_SPECIFY_INDEX_IMPLEMENTATION);
}
// If we explicitly specify the index type "legacy_local_table", we can just clear the custom class, and the
// non-custom 2i creation process will begin. Otherwise, if an index type has been specified with
// USING, make sure the appropriate custom index is created.
if (attrs.customClass != null)
{
if (!attrs.isCustom && attrs.customClass.equalsIgnoreCase(CassandraIndex.NAME))
attrs.customClass = null;
else
attrs.isCustom = true;
}
return new CreateIndexStatement(keyspaceName, tableName.getName(), indexName.getName(), rawIndexTargets, attrs, ifNotExists);
}
}
}
View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Add USING to the statement: CREATE CUSTOM INDEX ... ON t (col) USING 'StorageAttachedIndex'.
- Re-enable a default index implementation in cassandra.yaml (default_secondary_index setting).
- Set the desired custom index class explicitly in all migration scripts.
Example fix
// before CREATE INDEX idx ON t (col); // after CREATE CUSTOM INDEX idx ON t (col) USING 'StorageAttachedIndex';
Defensive patterns
Strategy: validation
Validate before calling
if (!cql.toLowerCase().contains("using") && !defaultSecondaryIndexEnabled()) throw new IllegalArgumentException("Add USING '<index implementation>' to CREATE INDEX"); Try / catch
try { session.execute(cql); } catch (InvalidQueryException e) { if (e.getMessage().contains("Must specify index implementation")) { /* append USING clause and retry */ } else throw e; } Prevention
- Always specify USING in CREATE INDEX statements for portability
- Track the default_secondary_index setting per environment
- Pin the index implementation explicitly in migration templates
When it happens
Trigger: `CREATE INDEX idx ON t (col);` while cassandra.yaml does not enable a default secondary index (DatabaseDescriptor.getDefaultSecondaryIndexEnabled() is false), so attrs.customClass stays null after prepare().
Common situations: Upgrading clusters where operators deliberately disabled the default 2i (e.g. after SAI adoption) and application DDL no longer specifies USING; fresh deployments with hardened config where the default was turned off.
Understand the failure class
Background: "Must pass :limit option" / "Missing required option" — required option errors explained — this error's family across 41 libraries.
Related errors
- Load CIDR groups cache operation not supported by %s
- native_transport_max_frame_size must be positive value < %dB
- %s
- Unable to parse targets for index %s (%s)
- Properties specified %s are not understood by %s
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/40d8acb9dba4eab6.
Report an issue: GitHub.