apache/cassandra · error · InvalidRequestException
Durations are not allowed as map keys:
Error message
Durations are not allowed as map keys:
What it means
InvalidRequestException during preparation of a map type: duration types cannot be used as map keys (non-frozen durations are not valid key types). The guard fires while preparing the collection's key type, alongside the analogous counter-in-collection check on values.
Source
Thrown at src/java/org/apache/cassandra/cql3/CQL3Type.java:875
assert values != null : "Got null values type for a collection";
if (!frozen && values.supportsFreezing() && !values.frozen)
throwNestedNonFrozenError(values);
// we represent supercolumns as maps, internally, and we do allow counters in supercolumns. Thus,
// for internal type parsing (think schema) we have to make an exception and allow counters as (map) values
if (values.isCounter() && !isInternal)
throw new InvalidRequestException("Counters are not allowed inside collections: " + this);
if (values.isDuration() && kind == Kind.SET)
throw new InvalidRequestException("Durations are not allowed inside sets: " + this);
if (keys != null)
{
if (keys.isCounter())
throw new InvalidRequestException("Counters are not allowed inside collections: " + this);
if (keys.isDuration())
throw new InvalidRequestException("Durations are not allowed as map keys: " + this);
if (!frozen && keys.supportsFreezing() && !keys.frozen)
throwNestedNonFrozenError(keys);
}
AbstractType<?> valueType = values.prepare(keyspace, udts).getType();
switch (kind)
{
case LIST:
return new Collection(ListType.getInstance(valueType, !frozen));
case SET:
return new Collection(SetType.getInstance(valueType, !frozen));
case MAP:
assert keys != null : "Got null keys type for a collection";
return new Collection(MapType.getInstance(keys.prepare(keyspace, udts).getType(), valueType, !frozen));
}
throw new AssertionError();
}
View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Use `map<time, ...>`, `map<timestamp, ...>`, or `frozen<duration>` is not allowed for keys either — use a text encoding of the duration as the key
- Use a duration as the map VALUE instead: map<text, duration> is allowed
- Model as a separate table with duration stored in a regular column
Example fix
// before CREATE TABLE t (id uuid PRIMARY KEY, by_interval map<duration, text>); // after CREATE TABLE t (id uuid PRIMARY KEY, by_interval map<text, duration>);
Defensive patterns
Strategy: validation
Validate before calling
boolean usesDurationAsMapKey(String cqlTypeDecl) {
java.util.regex.Matcher m = java.util.regex.Pattern.compile("map\\s*<\\s*([^,]+),").matcher(cqlTypeDecl.toLowerCase());
return m.find() && m.group(1).trim().equals("duration");
} Try / catch
try { session.execute(ddl); } catch (InvalidQueryException e) { if (e.getMessage().startsWith("Durations are not allowed as map keys")) { /* move duration to value position or use text key */ } else throw e; } Prevention
- Duration has no total ordering (months vs days) — exclude it from key/set positions
- Use map<text, duration> and keep the duration as the value
- Store comparable units (seconds) in bigint keys if interval-keyed lookup is needed
When it happens
Trigger: Declaring `map<duration, ...>` in CREATE TABLE / ALTER TABLE, or embedding a duration Raw type in the keys position of a map type.
Common situations: Users confusing duration with time or timestamp and using it as a map key for interval-keyed lookups.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Durations are not allowed inside sets:
- Invalid map literal for %s of type %s
- Durations are not allowed as map keys: %s
- category %s not found in %s
- 'Get CIDR groups for IP' operation not supported by %s
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/53d8347229128e22.
Report an issue: GitHub.