apache/cassandra · error · InvalidRequestException
Durations are not allowed as map keys: %s
Error message
Durations are not allowed as map keys: %s
What it means
A map literal/type in the selection clause uses duration as the key type. Durations cannot be map keys because they are not orderable, which map key ordering requires. The request is rejected at prepare time.
Source
Thrown at src/java/org/apache/cassandra/cql3/selection/Selectable.java:1143
throw invalidRequest("Cannot infer type for term %s in selection clause (try using a cast to force a type)",
this);
}
if (type.isUDT())
return newUdtSelectorFactory(cfm, expectedType, defs, boundNames);
return newMapSelectorFactory(cfm, defs, boundNames, type);
}
private Factory newMapSelectorFactory(TableMetadata cfm,
List<ColumnMetadata> defs,
VariableSpecifications boundNames,
AbstractType<?> type)
{
MapType<?, ?> mapType = (MapType<?, ?>) type;
if (mapType.getKeysType() == DurationType.instance)
throw invalidRequest("Durations are not allowed as map keys: %s", mapType.asCQL3Type());
return MapSelector.newFactory(type, getMapEntries(cfm).stream()
.map(p -> Pair.create(p.left.newSelectorFactory(cfm, mapType.getKeysType(), defs, boundNames),
p.right.newSelectorFactory(cfm, mapType.getValuesType(), defs, boundNames)))
.collect(Collectors.toList()));
}
private Factory newUdtSelectorFactory(TableMetadata cfm,
AbstractType<?> expectedType,
List<ColumnMetadata> defs,
VariableSpecifications boundNames)
{
UserType ut = (UserType) expectedType;
Map<FieldIdentifier, Factory> factories = new LinkedHashMap<>(ut.size());
for (Pair<Selectable.Raw, Selectable.Raw> raw : raws)
{
if (!(raw.left instanceof RawIdentifier))View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Move durations to the value side: map<text, duration> with durations as values.
- Use list<duration> or frozen<list<duration>> if an ordered container of durations is needed.
- Encode durations as orderable values (e.g. bigint seconds) for keys.
Example fix
// before
SELECT {5s:'a', 10s:'b'} FROM t; -- duration keys
// after
SELECT {'a':5s, 'b':10s} FROM t; -- durations as values Defensive patterns
Strategy: validation
Validate before calling
if (mapType.getKeysType().equals(DurationType.instance)) throw new IllegalArgumentException("duration cannot be a map key"); Try / catch
try { session.execute(stmt); } catch (InvalidRequestException e) { if (e.getMessage().startsWith("Durations are not allowed as map keys")) { /* move durations to values */ } else throw e; } Prevention
- Use map<orderable-type, duration>; never duration keys.
- Encode durations as bigint/timestamp if keying is required.
- Add schema-level linting that rejects duration key types.
When it happens
Trigger: `SELECT {1h:'a'} FROM t` — a map literal with duration keys; a term cast to map<duration, X>; schema where a map column's key type is duration and the literal is selected.
Common situations: Attempting to index durations by map keys; confusing map<duration,X> (invalid) with map<X,duration> (valid); typos swapping key/value types in the cast.
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
- Durations are not allowed as map keys:
- Durations are not allowed inside sets: %s
- Durations are not allowed inside sets:
- Unknown duration symbol '%s'
- ex.getMessage()
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/7c6ce75c469af377.
Report an issue: GitHub.