apache/flink · error · UnsupportedOperationException
Types that do not implement java.lang.Comparable cannot be u
Error message
Types that do not implement java.lang.Comparable cannot be used as keys.
What it means
Thrown by GenericTypeInfo.createComparator() when the type does not implement java.lang.Comparable. To be usable as a key, a generic type must be orderable; createComparator checks isKeyType() (which is Comparable.isAssignableFrom) and, failing that, refuses to build a comparator rather than producing a meaningless one.
Source
Thrown at flink-core/src/main/java/org/apache/flink/api/java/typeutils/GenericTypeInfo.java:110
return new KryoSerializer<T>(this.typeClass, config);
}
@SuppressWarnings("unchecked")
@Override
@PublicEvolving
public TypeComparator<T> createComparator(
boolean sortOrderAscending, ExecutionConfig executionConfig) {
if (isKeyType()) {
@SuppressWarnings("rawtypes")
GenericTypeComparator comparator =
new GenericTypeComparator(
sortOrderAscending,
createSerializer(executionConfig.getSerializerConfig()),
this.typeClass);
return (TypeComparator<T>) comparator;
}
throw new UnsupportedOperationException(
"Types that do not implement java.lang.Comparable cannot be used as keys.");
}
// --------------------------------------------------------------------------------------------
@Override
public int hashCode() {
return typeClass.hashCode();
}
@Override
public boolean canEqual(Object obj) {
return obj instanceof GenericTypeInfo;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof GenericTypeInfo) {View on GitHub (pinned to 2f3c205e92)
Solutions
- Implement Comparable on the class used as the key.
- Key by a specific Comparable field (a primitive/String) instead of the whole object: keyBy(MyType::getId).
- Convert the type into a proper POJO with KeySelector extraction of a Comparable field.
- Provide a custom TypeComparator via a TypeInfoFactory if you need bespoke ordering.
Example fix
// before DataStream<MyType> s = ...; s.keyBy(x -> x); // MyType generic, not Comparable -> throw // after s.keyBy(MyType::getId); // getId returns String/Long, Comparable // or make MyType implement Comparable<MyType>
Defensive patterns
Strategy: validation
Validate before calling
if (!Comparable.class.isAssignableFrom(MyType.class)) {
throw new IllegalStateException("MyType must implement Comparable to be a key");
} Type guard
static boolean isComparableKey(Class<?> c) {
return Comparable.class.isAssignableFrom(c);
} Prevention
- Key by a primitive/String field, not a whole generic object.
- Implement Comparable on classes used as keys.
- Use a KeySelector returning a Comparable type.
When it happens
Trigger: Calling keyBy() or a sort/minBy/maxBy on a DataStream whose type is a GenericTypeInfo whose class does not implement Comparable.
Common situations: Using a custom POJO that degraded to GenericTypeInfo as a grouping/sorting key without implementing Comparable; keying by a complex object that the type system treats as generic.
Related errors
- The type {} cannot be used as a key.
- The type {} is not Comparable.
- Unable to access field {} on object {}
- Cannot create Comparator for {typeClass.getCanonicalName()}.
- Input type of coGroup must be one of composite types or atom
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/c3d7f453d5ad452e.
Report an issue: GitHub.