apache/cassandra · error · InvalidRequestException

Value for a map substraction has to be a set, but was: '%s'

Error message

Value for a map substraction has to be a set, but was: '%s'

What it means

For a map subtraction (`m = m - ...`), the value term must prepare as a set of keys; the provided term failed its prepare() against that spec, so it is wrapped into this clearer error. The thrown message discards the underlying InvalidRequestException cause.

Source

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

            {
                case LIST:
                    return new Lists.Discarder(receiver, value.prepare(metadata.keyspace, receiver));
                case SET:
                    return new Sets.Discarder(receiver, value.prepare(metadata.keyspace, receiver));
                case MAP:
                    // The value for a map subtraction is actually a set
                    ColumnSpecification vr = new ColumnSpecification(receiver.ksName,
                                                                     receiver.cfName,
                                                                     receiver.name,
                                                                     SetType.getInstance(((MapType<?, ?>) receiver.type).getKeysType(), true));
                    Term term;
                    try
                    {
                        term = value.prepare(metadata.keyspace, vr);
                    }
                    catch (InvalidRequestException e)
                    {
                        throw new InvalidRequestException(String.format("Value for a map substraction has to be a set, but was: '%s'", value));
                    }
                    return new Sets.Discarder(receiver, term);
            }
            throw new AssertionError();
        }

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

        public boolean isCompatibleWith(RawUpdate other)
        {
            return !(other instanceof SetValue);
        }
    }

    public static class Prepend implements RawUpdate

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Pass a Set<K> of the keys to remove (not a Map) when subtracting from a map column
  2. Validate the key type matches the map's key type exactly
  3. Fix literal syntax: m = m - {key1, key2}
  4. Inspect the original cause by preparing the value separately if needed

Example fix

// before
Map<String,Integer> m = Map.of("k",1);
session.execute("UPDATE t SET m = m - ?", m);
// after
Set<String> keys = Set.of("k");
session.execute("UPDATE t SET m = m - ?", keys);
Defensive patterns

Strategy: validation

Validate before calling

if (!(keysToRemove instanceof Set<?> s)) throw new IllegalArgumentException("map subtraction requires a Set of keys");

Type guard

static boolean isSet(Object v){ return v instanceof Set; }

Try / catch

try { session.execute(ps.bind(keySet)); } catch (InvalidQueryException e) { if (e.getMessage().contains("has to be a set")) { /* pass Set<K> instead */ } else throw e; }

Prevention

When it happens

Trigger: `UPDATE t SET m = m - ?` where the bound value is not a set of the map's key type (e.g. a full map, a list, or a wrong key type); malformed set literal.

Common situations: Binding a Map instead of Set<K> of keys to remove; driver type mismatch; copying map-addition code (which takes a map) to subtraction without changing the argument type.

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/102f239fc94bb410. Report an issue: GitHub.