apache/flink · error · RuntimeException
Comparator {} specifies an invalid length for the normalized
Error message
Comparator {} specifies an invalid length for the normalized key: {} What it means
RowComparator.createAuxiliaryFields() validates that every sub-comparator that claims to support normalized keys reports a non-negative key length via getNormalizeKeyLen(). If a sub-comparator returns a negative length (a contract violation), this RuntimeException is thrown during comparator construction. The message names the offending comparator class and the invalid length value.
Source
Thrown at flink-core/src/main/java/org/apache/flink/api/java/typeutils/runtime/RowComparator.java:452
// key
if (k.supportsNormalizedKey()) {
if (i == 0) {
// the first comparator decides whether we need to invert the key direction
inverted = k.invertNormalizedKey();
} else if (k.invertNormalizedKey() != inverted) {
// if a successor does not agree on the inversion direction, it cannot be part
// of the
// normalized key
return new Tuple4<>(
normalizedKeyLengths,
numLeadingNormalizableKeys,
normalizableKeyPrefixLen,
inverted);
}
numLeadingNormalizableKeys++;
int len = k.getNormalizeKeyLen();
if (len < 0) {
throw new RuntimeException(
"Comparator "
+ k.getClass().getName()
+ " specifies an invalid length for the normalized key: "
+ len);
}
normalizedKeyLengths[i] = len;
normalizableKeyPrefixLen += len;
if (normalizableKeyPrefixLen < 0) {
// overflow, which means we are out of budget for normalized key space anyways
return new Tuple4<>(
normalizedKeyLengths,
numLeadingNormalizableKeys,
Integer.MAX_VALUE,
inverted);
}
} else {
return new Tuple4<>(
normalizedKeyLengths,View on GitHub (pinned to 2f3c205e92)
Solutions
- If you wrote a custom TypeComparator, override getNormalizeKeyLen() to return a non-negative int (>= 0) whenever supportsNormalizedKey() returns true.
- Audit the field types in the Row key: identify which one's comparator reports a negative normalized key length (the message includes the class name) and fix or replace that comparator.
- If the faulty comparator comes from a library, file a bug or avoid using that type as a Row key field.
- As a workaround, avoid using the problematic field type in the leading key positions of a Row key.
Example fix
// before — custom comparator claims normalized key support but returns -1
public class MyComparator extends TypeComparator<MyType> {
@Override public boolean supportsNormalizedKey() { return true; }
// getNormalizeKeyLen() inherited → returns -1 → RowComparator throws
}
// after — override getNormalizeKeyLen to return a valid non-negative length
public class MyComparator extends TypeComparator<MyType> {
@Override public boolean supportsNormalizedKey() { return true; }
@Override public int getNormalizeKeyLen() { return 8; } // fixed-length key
} Defensive patterns
Strategy: validation
Validate before calling
// Validate a custom TypeComparator's normalized-key contract
public static void validateComparatorContract(TypeComparator<?> cmp) {
if (cmp.supportsNormalizedKey() && cmp.getNormalizeKeyLen() < 0) {
throw new IllegalStateException(
cmp.getClass().getName()
+ " supports normalized keys but reports length "
+ cmp.getNormalizeKeyLen() + " (must be >= 0)");
}
} Try / catch
// createAuxiliaryFields throws during comparator construction (startup).
// Catch at the point where you build the RowComparator / TypeInformation.
try {
RowComparator cmp = new RowComparator(arity, keyPositions, comparators, ...);
} catch (RuntimeException e) {
if (e.getMessage().contains("invalid length for the normalized key")) {
log.error("A field comparator has a broken normalized-key contract", e);
// fix the comparator or avoid that field type in the key
}
throw e;
} Prevention
- When implementing a custom TypeComparator, always override getNormalizeKeyLen() if supportsNormalizedKey() returns true.
- Unit-test custom comparators for the normalized-key contract before using them in Row keys.
- Avoid using exotic or third-party field types in Row key positions.
- Validate the comparator contract in CI for all serialized types.
When it happens
Trigger: During RowComparator construction (which happens when Flink builds the TypeComparator for a Row used as a key in a DataSet sort/group/join), createAuxiliaryFields iterates the per-field NullAwareComparators. If one reports supportsNormalizedKey()==true but getNormalizeKeyLen() < 0, the exception fires. This indicates a bug in a custom TypeComparator implementation or an inconsistent comparator built via the type system.
Common situations: A custom TypeComparator implementation overrides supportsNormalizedKey() to return true but forgets to override getNormalizeKeyLen() (inheriting a default that returns -1); a composite/comparator wrapper miscomputes the normalized key length; a third-party connector or library provides a faulty TypeComparator for a field type used in a Row key.
Related errors
- Record serialization with leading normalized keys not suppor
- Record deserialization with leading normalized keys not supp
- Comparator {className} specifies an invalid length for the n
- 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/be7c905e4c170dab.
Report an issue: GitHub.