{"record":{"id":"37e5be0d4596e723","repo":"apache/flink","slug":"comparator-does-not-support-null-aware-serialized","errorCode":null,"errorMessage":"Comparator does not support null-aware serialized comparison.","messagePattern":"Comparator does not support null-aware serialized comparison\\.","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"flink-core/src/main/java/org/apache/flink/api/java/typeutils/runtime/NullAwareComparator.java","lineNumber":141,"sourceCode":"        else if (first == null) {\n            return order ? -1 : 1;\n        }\n        // second value is null -> inequality\n        // but order is considered\n        else if (second == null) {\n            return order ? 1 : -1;\n        }\n        // no null values\n        else {\n            return wrappedComparator.compare(first, second);\n        }\n    }\n\n    @Override\n    public int compareSerialized(DataInputView firstSource, DataInputView secondSource)\n            throws IOException {\n\n        throw new UnsupportedOperationException(\n                \"Comparator does not support null-aware serialized comparison.\");\n    }\n\n    @Override\n    public boolean supportsNormalizedKey() {\n        return wrappedComparator.supportsNormalizedKey();\n    }\n\n    @Override\n    public boolean supportsSerializationWithKeyNormalization() {\n        return false;\n    }\n\n    @Override\n    public int getNormalizeKeyLen() {\n        int len = wrappedComparator.getNormalizeKeyLen();\n        if (len == Integer.MAX_VALUE) {\n            return Integer.MAX_VALUE;","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/api/java/typeutils/runtime/NullAwareComparator.java#L123-L159","documentation":"NullAwareComparator.compareSerialized() always throws UnsupportedOperationException. The wrapper handles null references only in object form; deciding nullness from serialized bytes would require reading the null-flag byte, which the composite comparator (e.g. RowComparator) owns - so the wrapper forbids direct serialized comparison.","triggerScenarios":"A runtime path calls compareSerialized on a NullAwareComparator directly instead of going through its enclosing composite comparator - e.g. custom operators or join/co-group stubs that grab a field-level comparator and compare serialized forms; miswired sort/comparison logic in user extensions.","commonSituations":"User code extracts a TypeComparator from a composite type and invokes compareSerialized; third-party or custom runtime code assuming every TypeComparator supports serialized comparison.","solutions":["Do not call compareSerialized on null-aware field comparators; perform comparison through the owning composite comparator (RowComparator/TupleComparator)","Deserialize both values first, then use compare(first, second), which is null-aware","Restructure custom operator code to use TypeComparator APIs the wrapper supports (hash, compare, setReference)"],"exampleFix":"// before\nint cmp = nullAwareComparator.compareSerialized(in1, in2);\n\n// after\nT a = serializer.deserialize(in1);\nT b = serializer.deserialize(in2);\nint cmp = nullAwareComparator.compare(a, b);","handlingStrategy":"validation","validationCode":"if (comparator instanceof NullAwareComparator) {\n    // must compare via owning composite comparator or on-deserialized objects only\n}","typeGuard":"static boolean supportsSerializedComparison(TypeComparator<?> c) {\n    try {\n        // no probe API; conservative guard: NullAwareComparator never supports it\n        return !(c instanceof NullAwareComparator);\n    } catch (Exception e) {\n        return false;\n    }\n}","tryCatchPattern":"try {\n    cmp = comparator.compareSerialized(a, b);\n} catch (UnsupportedOperationException e) {\n    // fall back to deserialized comparison\n    A fa = serializer.deserialize(a);\n    A fb = serializer.deserialize(b);\n    cmp = comparator.compare(fa, fb);\n}","preventionTips":["Never call compareSerialized on field-level null-aware comparators","Route comparisons through composite comparators (RowComparator/TupleComparator)","Unit-test custom operators against nullable key types"],"tags":["comparator","null-handling","serialized-comparison","unsupported-operation"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}