apache/cassandra · error · InvalidRequestException
Invalid map literal for
Error message
Invalid map literal for %s: bind variables are not supported inside collection literals
What it means
Cassandra map literals (e.g. `SET m = {'a': 1}`) cannot contain bind markers inside them; the whole literal must either be a literal or bound as a single value. During prepare, if any key or term of the map literal contains a bind marker, preparation fails.
Solutions
- Bind the entire map as one parameter: `SET m = ?` and pass a Map value.
- Use literals directly in the map: `SET m = {'key': 'value'}`.
- For a single key update use positional key binding on the accessor form `m[?] = ?`, not inside a literal.
Example fix
// before
"UPDATE t SET m = {? : ?} WHERE k=?"
// after
"UPDATE t SET m[?] = ? WHERE k=?" // or bind whole map: SET m = ? Defensive patterns
Strategy: validation
Validate before calling
if (query.matches(".*\{[^}]*\?.*\}.*")) throw new IllegalArgumentException("bind markers not allowed inside map literals"); Try / catch
try { session.prepare(sql); } catch (InvalidRequestException e) { if (e.getMessage().contains("bind variables are not supported inside collection literals")) { /* rewrite query */ } else throw e; } Prevention
- Bind whole collections as single parameters (SET m = ?)
- Use m[?] = ? form for per-key updates
- Review query templates for ? inside {} or [] literals
When it happens
Trigger: Preparing a statement like `INSERT ... SET m = {? : ?}` or `UPDATE ... SET m['?'] = ?` where a bind marker appears inside a map literal's entries.
Common situations: Developers assuming named parameters work anywhere in a statement; query builders interpolating bind markers into collection literals; migrating code from concatenation to parameterized queries.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Cannot create ENTRIES index on frozen map clustering column
- Cannot create index on
- Cannot infer type for term
- cannot parse map value from
- Cannot parse map value from
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/8fc6e98e04ab450d.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/cql3/terms/Maps.java:195
public Term prepare(String keyspace, ColumnSpecification receiver) throws InvalidRequestException
{
validateAssignableTo(keyspace, receiver);
ColumnSpecification keySpec = Maps.keySpecOf(receiver);
ColumnSpecification valueSpec = Maps.valueSpecOf(receiver);
// In CQL maps are represented as a list of key value pairs (e.g. {k1 : v1, k2 : v2, ...}).
// Whereas, internally maps are serialized as a lists where each key is followed by its value (e.g. [k1, v1, k2, v2, ...])
// Therefore, we must go from one format to another.
List<Term> values = new ArrayList<>(entries.size() << 1);
boolean allTerminal = true;
for (Pair<Term.Raw, Term.Raw> entry : entries)
{
Term k = entry.left.prepare(keyspace, keySpec);
Term v = entry.right.prepare(keyspace, valueSpec);
if (k.containsBindMarker() || v.containsBindMarker())
throw new InvalidRequestException(String.format("Invalid map literal for %s: bind variables are not supported inside collection literals", receiver.name));
if (k instanceof Term.NonTerminal || v instanceof Term.NonTerminal)
allTerminal = false;
values.add(k);
values.add(v);
}
MultiElements.DelayedValue value = new MultiElements.DelayedValue((MultiElementType<?>) receiver.type.unwrap(), values);
return allTerminal ? value.bind(QueryOptions.DEFAULT) : value;
}
private void validateAssignableTo(String keyspace, ColumnSpecification receiver) throws InvalidRequestException
{
AbstractType<?> type = receiver.type.unwrap();
if (!(type instanceof MapType))
throw new InvalidRequestException(String.format("Invalid map literal for %s of type %s", receiver.name, receiver.type.asCQL3Type()));
View on GitHub (pinned to 88fd0f6a0e)