{"record":{"id":"c3d7f453d5ad452e","repo":"apache/flink","slug":"types-that-do-not-implement-java-lang-comparable-c","errorCode":null,"errorMessage":"Types that do not implement java.lang.Comparable cannot be used as keys.","messagePattern":"Types that do not implement java\\.lang\\.Comparable cannot be used as keys\\.","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"flink-core/src/main/java/org/apache/flink/api/java/typeutils/GenericTypeInfo.java","lineNumber":110,"sourceCode":"        return new KryoSerializer<T>(this.typeClass, config);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    @Override\n    @PublicEvolving\n    public TypeComparator<T> createComparator(\n            boolean sortOrderAscending, ExecutionConfig executionConfig) {\n        if (isKeyType()) {\n            @SuppressWarnings(\"rawtypes\")\n            GenericTypeComparator comparator =\n                    new GenericTypeComparator(\n                            sortOrderAscending,\n                            createSerializer(executionConfig.getSerializerConfig()),\n                            this.typeClass);\n            return (TypeComparator<T>) comparator;\n        }\n\n        throw new UnsupportedOperationException(\n                \"Types that do not implement java.lang.Comparable cannot be used as keys.\");\n    }\n\n    // --------------------------------------------------------------------------------------------\n\n    @Override\n    public int hashCode() {\n        return typeClass.hashCode();\n    }\n\n    @Override\n    public boolean canEqual(Object obj) {\n        return obj instanceof GenericTypeInfo;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (obj instanceof GenericTypeInfo) {","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/api/java/typeutils/GenericTypeInfo.java#L92-L128","documentation":"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.","triggerScenarios":"Calling keyBy() or a sort/minBy/maxBy on a DataStream whose type is a GenericTypeInfo whose class does not implement Comparable.","commonSituations":"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.","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."],"exampleFix":"// before\nDataStream<MyType> s = ...;\ns.keyBy(x -> x); // MyType generic, not Comparable -> throw\n\n// after\ns.keyBy(MyType::getId); // getId returns String/Long, Comparable\n// or make MyType implement Comparable<MyType>","handlingStrategy":"validation","validationCode":"if (!Comparable.class.isAssignableFrom(MyType.class)) {\n    throw new IllegalStateException(\"MyType must implement Comparable to be a key\");\n}","typeGuard":"static boolean isComparableKey(Class<?> c) {\n    return Comparable.class.isAssignableFrom(c);\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["key-type","comparator","generic-type","keyed-stream"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}