google/gson · error · ClassCastException

{className} is not Comparable

Error message

{className} is not Comparable

What it means

Thrown by LinkedTreeMap.find() as a ClassCastException ('<className> is not Comparable') when the map is using natural ordering (no comparator supplied) and the first key inserted does not implement Comparable. LinkedTreeMap orders keys via compareTo; without a Comparator and without Comparable keys it has no way to position nodes, so it rejects the key rather than producing undefined ordering.

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 8b8628c656)

Solutions

  1. Make the key class implement Comparable and implement compareTo consistently with equals.
  2. Supply a Comparator when creating the map: new LinkedTreeMap<>(myComparator, true).
  3. Use a HashMap/LinkedHashMap if you only need hash-based keys and do not require ordering.

Example fix

// before
class Key { String id; } // not Comparable
LinkedTreeMap<Key, Integer> m = new LinkedTreeMap<>();
m.put(new Key(), 1); // throws

// after: implement Comparable
 class Key implements Comparable<Key> {
   public int compareTo(Key o) { return id.compareTo(o.id); }
 }
Defensive patterns

Strategy: type-guard

Validate before calling

static boolean isComparableKey(Object key) {
  return key instanceof Comparable;
}
// usage: if (!isComparableKey(k)) throw new IllegalArgumentException("key must be Comparable");

Type guard

static <K> boolean keyTypeIsComparable(Class<K> type) {
  return Comparable.class.isAssignableFrom(type);
}

Try / catch

try {
  map.put(key, value);
} catch (ClassCastException e) {
  if (e.getMessage().contains("not Comparable")) {
    // rebuild the map with an explicit Comparator and retry
    map = new LinkedTreeMap<>(myComparator, map.allowNullValues);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling put(key, value) where key's class does not implement Comparable, on a LinkedTreeMap created with the no-arg or LinkedTreeMap(boolean) constructors (natural order). The check only fires on the first insertion because that is the first time a comparison would be attempted.

Common situations: Using a POJO/domain class as a map key without implementing Comparable; Gson deserializing into a Map<MyPojo, V> where MyPojo is not Comparable; mixing key types inadvertently.

Related errors


AI-assisted analysis of google/gson@8b8628c656 (2026-08-04). Data as JSON: /data/errors/89cab2c91d5b33f6.json. Report an issue: GitHub.