apache/flink · error · UnsupportedOperationException

Comparator does not support null-aware serialized comparison

Error message

Comparator does not support null-aware serialized comparison.

What it means

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.

Source

Thrown at flink-core/src/main/java/org/apache/flink/api/java/typeutils/runtime/NullAwareComparator.java:141

        else if (first == null) {
            return order ? -1 : 1;
        }
        // second value is null -> inequality
        // but order is considered
        else if (second == null) {
            return order ? 1 : -1;
        }
        // no null values
        else {
            return wrappedComparator.compare(first, second);
        }
    }

    @Override
    public int compareSerialized(DataInputView firstSource, DataInputView secondSource)
            throws IOException {

        throw new UnsupportedOperationException(
                "Comparator does not support null-aware serialized comparison.");
    }

    @Override
    public boolean supportsNormalizedKey() {
        return wrappedComparator.supportsNormalizedKey();
    }

    @Override
    public boolean supportsSerializationWithKeyNormalization() {
        return false;
    }

    @Override
    public int getNormalizeKeyLen() {
        int len = wrappedComparator.getNormalizeKeyLen();
        if (len == Integer.MAX_VALUE) {
            return Integer.MAX_VALUE;

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Do not call compareSerialized on null-aware field comparators; perform comparison through the owning composite comparator (RowComparator/TupleComparator)
  2. Deserialize both values first, then use compare(first, second), which is null-aware
  3. Restructure custom operator code to use TypeComparator APIs the wrapper supports (hash, compare, setReference)

Example fix

// before
int cmp = nullAwareComparator.compareSerialized(in1, in2);

// after
T a = serializer.deserialize(in1);
T b = serializer.deserialize(in2);
int cmp = nullAwareComparator.compare(a, b);
Defensive patterns

Strategy: validation

Validate before calling

if (comparator instanceof NullAwareComparator) {
    // must compare via owning composite comparator or on-deserialized objects only
}

Type guard

static boolean supportsSerializedComparison(TypeComparator<?> c) {
    try {
        // no probe API; conservative guard: NullAwareComparator never supports it
        return !(c instanceof NullAwareComparator);
    } catch (Exception e) {
        return false;
    }
}

Try / catch

try {
    cmp = comparator.compareSerialized(a, b);
} catch (UnsupportedOperationException e) {
    // fall back to deserialized comparison
    A fa = serializer.deserialize(a);
    A fb = serializer.deserialize(b);
    cmp = comparator.compare(fa, fb);
}

Prevention

When it happens

Trigger: 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.

Common situations: User code extracts a TypeComparator from a composite type and invokes compareSerialized; third-party or custom runtime code assuming every TypeComparator supports serialized comparison.

Related errors


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