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
- 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)
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
- Never call compareSerialized on field-level null-aware comparators
- Route comparisons through composite comparators (RowComparator/TupleComparator)
- Unit-test custom operators against nullable key types
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
- Record serialization with leading normalized keys not suppor
- Record deserialization with leading normalized keys not supp
- Workaround hack.
- Record serialization with leading normalized keys not suppor
- Record deserialization with leading normalized keys not supp
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/37e5be0d4596e723.
Report an issue: GitHub.