apache/cassandra · error · InvalidRequestException

Invalid operation (%s) for set column %s

Error message

Invalid operation (%s) for set column %s

What it means

Cassandra throws this during preparation when a keyed collection operation (map put-by-key or list set-by-index pattern) is applied to a set column. Sets have no keys or indices, so SetterByKey/index-style operations are invalid for them; only full assignment or set addition/subtraction is allowed.

Source

Thrown at src/java/org/apache/cassandra/cql3/Operation.java:261

            this.selector = selector;
            this.value = value;
        }

        public Operation prepare(TableMetadata metadata, ColumnMetadata receiver, boolean canReadExistingState) throws InvalidRequestException
        {
            if (!(receiver.type instanceof CollectionType))
                throw new InvalidRequestException(String.format("Invalid operation (%s) for non collection column %s", toString(receiver), receiver.name));
            else if (!(receiver.type.isMultiCell()))
                throw new InvalidRequestException(String.format("Invalid operation (%s) for frozen collection column %s", toString(receiver), receiver.name));

            switch (((CollectionType<?>)receiver.type).kind)
            {
                case LIST:
                    Term idx = selector.prepare(metadata.keyspace, Lists.indexSpecOf(receiver));
                    Term lval = value.prepare(metadata.keyspace, Lists.valueSpecOf(receiver));
                    return new Lists.SetterByIndex(receiver, idx, lval);
                case SET:
                    throw new InvalidRequestException(String.format("Invalid operation (%s) for set column %s", toString(receiver), receiver.name));
                case MAP:
                    Term key = selector.prepare(metadata.keyspace, Maps.keySpecOf(receiver));
                    Term mval = value.prepare(metadata.keyspace, Maps.valueSpecOf(receiver));
                    return new Maps.SetterByKey(receiver, key, mval);
            }
            throw new AssertionError();
        }

        protected String toString(ColumnSpecification column)
        {
            return String.format("%s[%s] = %s", column.name, selector, value);
        }

        public boolean isCompatibleWith(RawUpdate other)
        {
            // TODO: we could check that the other operation is not setting the same element
            // too (but since the index/key set may be a bind variables we can't always do it at this point)
            return !(other instanceof SetValue);

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Use set add/remove instead of key assignment: SET myset = myset + {'v'} or myset - {'v'}
  2. Verify the column type with DESCRIBE TABLE; if key->value semantics are needed, change the column to map<K,V> (via migration)
  3. Fix code generation/ORM mapping so sets never receive by-key operations

Example fix

// before (myset is set<text>)
UPDATE users SET myset['role'] = 'admin' WHERE id = 1;
// after
UPDATE users SET myset = myset + {'admin'} WHERE id = 1;
Defensive patterns

Strategy: validation

Validate before calling

AbstractType<?> t = tm.getColumn(col).getType();
if (t instanceof CollectionType && ((CollectionType<?>) t).kind == CollectionType.Kind.SET)
    throw new IllegalArgumentException("sets have no keys/indices; use + / - operators");

Type guard

boolean isSet(AbstractType<?> t) { return t instanceof CollectionType && ((CollectionType<?>) t).kind == CollectionType.Kind.SET; }

Prevention

When it happens

Trigger: Using element/key assignment syntax on a set column, e.g. 'UPDATE t SET myset['k']='v' WHERE ...' or an index-style operation myset[0]=x where myset is set<T>; the prepare() switch on CollectionType.Kind reaches the SET case and rejects it.

Common situations: Confusion between set and map column types in the schema; application code templated for maps reused for sets; column type changed from map to set in a migration.

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/105b98ca6f1281d3. Report an issue: GitHub.