apache/flink · error · UnsupportedOperationException

Types that do not implement java.lang.Comparable cannot be…

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.

Solutions

  1. Implement Comparable on the class used as the key.
  2. Key by a specific Comparable field (a primitive/String) instead of the whole object: keyBy(MyType::getId).
  3. Convert the type into a proper POJO with KeySelector extraction of a Comparable field.
  4. 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

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


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/c3d7f453d5ad452e. Report an issue: GitHub.

Appendix: 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)