apache/cassandra · error · InvalidTypeException
Invalid type for map key, expecting %s but got %s
Error message
Invalid type for map key, expecting %s but got %s
What it means
Thrown by MapCodec.serialize() when a map key cannot be serialized by the key codec — the ClassCastException from keyCodec.serialize is wrapped in an InvalidTypeException naming the expected Java type and the actual key class. The map's runtime key type does not match the codec's declared key type.
Source
Thrown at src/java/org/apache/cassandra/cql3/functions/types/TypeCodec.java:2465
{
if (value == null) return null;
int i = 0;
ByteBuffer[] bbs = new ByteBuffer[2 * value.size()];
for (Map.Entry<K, V> entry : value.entrySet())
{
ByteBuffer bbk;
K key = entry.getKey();
if (key == null)
{
throw new NullPointerException("Map keys cannot be null");
}
try
{
bbk = keyCodec.serialize(key, protocolVersion);
}
catch (ClassCastException e)
{
throw new InvalidTypeException(
String.format(
"Invalid type for map key, expecting %s but got %s",
keyCodec.getJavaType(), key.getClass()),
e);
}
ByteBuffer bbv;
V v = entry.getValue();
if (v == null)
{
throw new NullPointerException("Map values cannot be null");
}
try
{
bbv = valueCodec.serialize(v, protocolVersion);
}
catch (ClassCastException e)
{
throw new InvalidTypeException(View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Ensure the Map's key type matches keyCodec.getJavaType() (e.g. build Map<Integer,String> for an int-keyed map)
- Check the actual column type and obtain the codec via TypeCodec.map(keyType, valueType)
- Convert keys explicitly (e.g. ((Number)k).intValue()) before serializing
Example fix
// before Map<Long,String> m = ...; MapCodec<Integer,String> codec = TypeCodec.map(INT, TEXT); codec.serialize(m, version); // InvalidTypeException // after Map<Integer,String> fixed = new HashMap<>(); m.forEach((k,v) -> fixed.put(k.intValue(), v)); codec.serialize(fixed, version);
Defensive patterns
Strategy: type-guard
Validate before calling
for (Object k : map.keySet()) {
if (!keyCodec.getJavaType().getRawType().isInstance(k))
throw new IllegalArgumentException("Key " + k + " is " + k.getClass() + ", expected " + keyCodec.getJavaType());
}
codec.serialize(map, protocolVersion); Type guard
static <K,V> boolean keysMatch(Map<?,?> m, TypeCodec<K,V> codec) {
return m.keySet().stream().allMatch(k ->
codec.getJavaType().getRawType().isInstance(k));
} Try / catch
try {
codec.serialize(map, protocolVersion);
} catch (InvalidTypeException e) {
if (e.getMessage().startsWith("Invalid type for map key")) {
Map<Object,Object> converted = convertKeys(map, keyCodec);
return codec.serialize(converted, protocolVersion);
}
throw e;
} Prevention
- Use fully parameterized generics (no raw Map) so mismatches surface at compile time
- Verify the codec's declared types match the column definition (TypeCodec.map(keyType, valType))
- Convert numeric key types explicitly (Integer vs Long)
When it happens
Trigger: Calling MapCodec.serialize() with a Map whose keys are of the wrong Java type, e.g. a Map<Long,String> passed to a MapCodec<Integer,String>, or raw-typed/mixed maps containing heterogeneous keys.
Common situations: Raw-typed maps bypassing generics; mixing Integer and Long keys after numeric parsing; passing a map built for a different column definition; generic type erasure hiding the mismatch until runtime.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Map keys cannot be null
- Map values cannot be null
- Function %s requires a map argument, but found argument %s o
- Invalid value for CQL type ${toDataType().getName()}
- Invalid 32-bits integer value, expecting 4 bytes but got %d
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/c924891605bf0e22.
Report an issue: GitHub.