apache/cassandra · error · InvalidRequestException

Cannot specify index class for a non-CUSTOM index

Error message

Cannot specify index class for a non-CUSTOM index

What it means

The index class option (`USING '<class>'` / `customClass`) is only meaningful for CUSTOM indexes. Supplying a class with a non-custom `CREATE INDEX` is contradictory, so validate() rejects it with InvalidRequestException.

Source

Thrown at src/java/org/apache/cassandra/cql3/statements/schema/IndexAttributes.java:54

    private static final Set<String> obsoleteKeywords = new HashSet<>();

    public boolean isCustom;
    public String customClass;

    static
    {
        keywords.add(KW_OPTIONS);
    }

    public void validate() throws RequestValidationException
    {
        validate(keywords, obsoleteKeywords);

        if (isCustom && customClass == null)
            throw new InvalidRequestException("CUSTOM index requires specifiying the index class");

        if (!isCustom && customClass != null)
            throw new InvalidRequestException("Cannot specify index class for a non-CUSTOM index");

        if (!isCustom && !properties.isEmpty())
            throw new InvalidRequestException("Cannot specify options for a non-CUSTOM index");

        if (getRawOptions().containsKey(IndexTarget.CUSTOM_INDEX_OPTION_NAME))
            throw new InvalidRequestException(String.format("Cannot specify %s as a CUSTOM option",
                                                            IndexTarget.CUSTOM_INDEX_OPTION_NAME));

        if (getRawOptions().containsKey(IndexTarget.TARGET_OPTION_NAME))
            throw new InvalidRequestException(String.format("Cannot specify %s as a CUSTOM option",
                                                            IndexTarget.TARGET_OPTION_NAME));

    }

    private Map<String, String> getRawOptions() throws SyntaxException
    {
        Map<String, String> options = getMap(KW_OPTIONS);
        return options == null ? Collections.emptyMap() : options;

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Add the CUSTOM keyword: `CREATE CUSTOM INDEX i ON t (col) USING '<class>';` if a custom index was intended.
  2. Remove the `USING '<class>'` clause if a plain built-in secondary index was intended.
  3. Remember custom indexes also require the class name plus, optionally, OPTIONS.

Example fix

-- before
CREATE INDEX i ON t (col) USING 'StorageAttachedIndex';

-- after
CREATE CUSTOM INDEX i ON t (col) USING 'StorageAttachedIndex';
Defensive patterns

Strategy: validation

Validate before calling

boolean hasCustom = ddl.matches("(?i)CREATE\\s+CUSTOM\\s+INDEX");
boolean hasUsing  = ddl.matches("(?i)USING\\s+'[^']+'");
if (!hasCustom && hasUsing) throw new IllegalArgumentException("USING requires the CUSTOM keyword");

Try / catch

try { session.execute(ddl); }
catch (InvalidQueryException e) {
  if (e.getMessage().contains("non-CUSTOM index"))
      throw new IllegalArgumentException("either drop USING or add the CUSTOM keyword", e);
  throw e;
}

Prevention

When it happens

Trigger: `CREATE INDEX i ON t (col) USING 'SomeIndexClass';` — a USING clause without the CUSTOM keyword.

Common situations: Users thinking `USING` alone creates a custom index (forgot the CUSTOM keyword); copy-pasted DDL where CUSTOM was dropped; confusion between built-in 2i and custom index syntax.

Related errors


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