apache/cassandra · error · InvalidRequestException

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

Error message

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

What it means

Cassandra throws this when a map addition operation like `m = m + {...}` is given a value that fails to prepare as a map. The raw term (a literal, bind marker, or expression) could not be parsed/validated against the map type of the target column, so the statement is rejected at prepare (validation) time.

Source

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

            }
            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:
                    return new Lists.Appender(receiver, value.prepare(metadata.keyspace, receiver));
                case SET:
                    return new Sets.Adder(receiver, value.prepare(metadata.keyspace, receiver));
                case MAP:
                    Term term;
                    try
                    {
                        term = value.prepare(metadata.keyspace, receiver);
                    }
                    catch (InvalidRequestException e)
                    {
                        throw new InvalidRequestException(String.format("Value for a map addition has to be a map, but was: '%s'", value));
                    }

                    return new Maps.Putter(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);
        }
    }

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Inspect the value being added; ensure it is declared/serialized as the exact map<K,V> type of the column
  2. Use named bound values and confirm the driver-side type matches (e.g. Map<String,Integer> for map<text,int>)
  3. Rewrite a malformed literal into valid map literal syntax: {key: value, ...}
  4. Check for unset/null bind markers supplied where a map value was required

Example fix

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

Strategy: validation

Validate before calling

if (!(value instanceof Map<?,?> m)) throw new IllegalArgumentException("map addition requires a Map, got " + value.getClass());

Type guard

static boolean isMap(Object v){ return v instanceof Map; }

Try / catch

try { session.execute(ps.bind(mapValue)); } catch (InvalidQueryException e) { if (e.getMessage().contains("has to be a map")) { /* fix bind type */ } else throw e; }

Prevention

When it happens

Trigger: `UPDATE ... SET m = m + ?` or `SET m = m + <literal>` where the bound value or literal is not a valid map (e.g. binding a list/set/JSON value, malformed literal like a bare set, or a bind marker left unset/wrong type).

Common situations: Passing a JSON object as a List/ByteBuffer via the driver without mapping it to Map; driver type mismatches between app language and CQL map<_,_>; typo in literal syntax producing a non-map term.

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/0ca95e2e2d7825a3. Report an issue: GitHub.