apache/cassandra · error · InvalidRequestException

Cannot create index on %s of column %s with non-map type

Error message

Cannot create index on %s of column %s with non-map type

What it means

KEYS and KEYS_AND_VALUES (ENTRIES-style) index targets are only valid on map columns, since only maps have keys. Applying them to a list or set (or any non-map type) is rejected. Raised when baseType is not a MapType and target.type is KEYS or KEYS_AND_VALUES.

Source

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

            throw ire(ONLY_PARTITION_KEY, column);

        if (target.type == Type.FULL && isNonSAIIndex && (!baseType.isCollection() || column.type.isMultiCell()))
            throw ire(FULL_ON_FROZEN_COLLECTIONS);

        if (!baseType.isCollection() && target.type != Type.SIMPLE)
            throw ire(NON_COLLECTION_SIMPLE_INDEX, target.type, column);

        // Frozen collections are only supported with SAI indexes.
        if (isNonSAIIndex && baseType.isCollection() && !column.type.isMultiCell())
        {
            if (target.type == Type.VALUES || target.type == Type.KEYS || target.type == Type.KEYS_AND_VALUES)
            {
                throw ire(CREATE_ON_FROZEN_COLUMN, target.type.toString(), column.name, column.name);
            }
        }

        if (!(baseType instanceof MapType) && (target.type == Type.KEYS || target.type == Type.KEYS_AND_VALUES ))
            throw ire(CREATE_WITH_NON_MAP_TYPE, target.type, column);

        // Can't query map[key]=value on clustering key columns, so ENTRIES index would be not queryable.
        if (column.isClusteringColumn() && baseType instanceof MapType && !column.type.isMultiCell()
            && target.type == Type.KEYS_AND_VALUES)
            throw ire(ENTRIES_INDEX_ON_FROZEN_MAP_CLUSTERING_KEY_NOT_SUPPORTED, column.name);

        if (column.type.isUDT() && column.type.isMultiCell())
            throw ire(CREATE_ON_NON_FROZEN_UDT, column);
    }

    /**
     * Checks if the given index attributes represent a Storage Attached Index.
     */
    private boolean isSAIIndex(IndexAttributes attrs)
    {
        return attrs.isCustom && IndexMetadata.isSAIIndex(attrs.customClass);
    }

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. For lists and sets use a plain (VALUES) index: CREATE INDEX ON t (my_list).
  2. Keep keys()/entries() only for map<...> columns.
  3. If key-based lookup is needed on list data, remodel as a map or a query table.

Example fix

// before
CREATE INDEX ON t (keys(scores)); // scores: list<int>
// after
CREATE INDEX ON t (scores);
Defensive patterns

Strategy: validation

Validate before calling

if (!(baseType instanceof MapType) && ['KEYS','KEYS_AND_VALUES'].includes(target.type)) throw new Error('keys()/entries() targets must be map columns');

Type guard

const keysTargetValid = (t) => t instanceof MapType;

Try / catch

try { session.execute(ddl); } catch (e) { if (/non-map type/.test(e.message)) { /* use plain index or fix the column */ } else throw e; }

Prevention

When it happens

Trigger: `CREATE INDEX ON t (keys(my_list))` or `keys_and_values(my_set)` where the column is list<...>, set<...>, or a non-collection type.

Common situations: Confusing list indexes (VALUES only) with map indexes; script-generated index DDL applying keys() to all collections; switching a column from map to list without updating indexes.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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