google/gson · error · ClassCastException
${key.getClass().getName()} is not Comparable
Error message
${key.getClass().getName()} is not Comparable What it means
LinkedTreeMap in natural-ordering mode (no comparator) requires keys that implement Comparable. When the first key is inserted into an empty tree and the key is not instanceof Comparable, a ClassCastException is thrown (LinkedTreeMap.java:183) because there is no way to order it.
Source
Thrown at gson/src/main/java/com/google/gson/internal/LinkedTreeMap.java:184
break;
}
nearest = child;
}
}
// The key doesn't exist in this tree.
if (!create) {
return null;
}
// Create the node and add it to the tree or the table.
Node<K, V> header = this.header;
Node<K, V> created;
if (nearest == null) {
// Check that the value is comparable if we didn't do any comparisons.
if (comparator == null && !(key instanceof Comparable)) {
throw new ClassCastException(key.getClass().getName() + " is not Comparable");
}
created = new Node<>(allowNullValues, nearest, key, header, header.prev);
root = created;
} else {
created = new Node<>(allowNullValues, nearest, key, header, header.prev);
if (comparison < 0) { // nearest.key is higher
nearest.left = created;
} else { // comparison > 0, nearest.key is lower
nearest.right = created;
}
rebalance(nearest, true);
}
size++;
modCount++;
return created;
}
View on GitHub (pinned to 310ac341f2)
Solutions
- Implement Comparable on the key type, or pass a Comparator to the LinkedTreeMap constructor: new LinkedTreeMap<>(comparator, allowNullValues).
- Use a HashMap keyed on a stable String/int field derived from the object instead of the object itself.
- If keys are heterogeneous, define a Comparator that imposes a total order over all expected key types.
Example fix
// before
class Key { String id; } // not Comparable
map.put(new Key(), value); // throws on first insert
// after (option A: Comparable)
class Key implements Comparable<Key> {
public int compareTo(Key o){ return id.compareTo(o.id); }
}
// after (option B: comparator)
new LinkedTreeMap<Key,V>(Comparator.comparing(k -> k.id), true); Defensive patterns
Strategy: validation
Validate before calling
if (key != null && !(key instanceof Comparable) && comparator == null) throw new ClassCastException("key must be Comparable"); Type guard
static boolean keyTypeOK(Class<?> k, Comparator<?> cmp) { return cmp != null || Comparable.class.isAssignableFrom(k); } Try / catch
try { map.put(k, v); } catch (ClassCastException e) { /* non-comparable key */ } Prevention
- Implement Comparable on any class you intend to use as a key.
- Pass an explicit Comparator to the LinkedTreeMap constructor when keys are not Comparable.
- Prefer scalar/String keys derived from objects over the objects themselves.
When it happens
Trigger: Calling put on an empty LinkedTreeMap (natural order) whose key class does not implement Comparable, e.g. putting a POJO or array as a key.
Common situations: Using custom domain objects as map keys without implementing Comparable; using arrays or non-Comparable wrappers as keys; mixing key types across puts that are not mutually comparable.
Related errors
- key == null
- value == null
- Deserialization is unsupported
- Element must be non-null
- Not a JSON Object: ${this}
AI-assisted analysis of google/gson@310ac341f2 (2026-08-10).
Data as JSON: /api/errors/bb6d8e78b83a178f.
Report an issue: GitHub.