apache/flink · error · RuntimeException

A NullPointerException occurred while accessing a key field

Error message

A NullPointerException occurred while accessing a key field in a POJO. Most likely, the value grouped/joined on is null. Field name: {}

What it means

Thrown by PojoComparator.hash() when computing the hash of a key field raises NullPointerException: this happens when the key FIELD value is null (the field itself was read, but hashing null via the field comparator, or the access chain, NPEs). The message names the exact field whose value is null.

Source

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

                    "This should not happen since we call setAccesssible(true) in the ctor."
                            + " fields: "
                            + field
                            + " obj: "
                            + object);
        }
        return object;
    }

    @Override
    public int hash(T value) {
        int i = 0;
        int code = 0;
        for (; i < this.keyFields.length; i++) {
            code *= TupleComparatorBase.HASH_SALT[i & 0x1F];
            try {
                code += this.comparators[i].hash(accessField(keyFields[i], value));
            } catch (NullPointerException npe) {
                throw new RuntimeException(
                        "A NullPointerException occurred while accessing a key field in a POJO. "
                                + "Most likely, the value grouped/joined on is null. Field name: "
                                + keyFields[i].getName(),
                        npe);
            }
        }
        return code;
    }

    @Override
    public void setReference(T toCompare) {
        int i = 0;
        for (; i < this.keyFields.length; i++) {
            this.comparators[i].setReference(accessField(keyFields[i], toCompare));
        }
    }

    @Override

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Do not key on nullable fields - map nulls to a sentinel value before keyBy (e.g. Optional.map(...).orElse(DEFAULT))
  2. Filter or side-output records with null keys before the keyBy/groupBy operator
  3. Read the field name in the message to pinpoint which key column is null

Example fix

// before
d.keyBy(pojo -> pojo.getRegion()) // region may be null

// after
d.map(p -> p.getRegion() == null ? "__unknown__" : p.getRegion())
 .keyBy(r -> r);
Defensive patterns

Strategy: validation

Validate before calling

// ensure key field is non-null before keyBy
if (pojo.getKeyField() == null) {
    sideOutputOrDefault(pojo); // route away or fill sentinel
}

Type guard

static boolean hasNonNullKey(MyPojo p) {
    return p != null && p.getKeyField() != null;
}

Try / catch

try {
    keyedStream = stream.keyBy(keySelector);
} // hash() runs later inside the operator; catch at operator level:
catch (RuntimeException e) {
    if (e.getMessage() != null && e.getMessage().contains("grouped/joined on is null")) {
        // null key field detected - fix upstream data quality
    }
    throw e;
}

Prevention

When it happens

Trigger: keyBy/groupBy on a POJO field that is null in some records: code *= HASH_SALT; comparators[i].hash(accessField(...)) throws NPE on the null field value, and PojoComparator rethrows with the field name.

Common situations: Optional POJO fields used as keys without null filtering; upstream services emitting partially-filled records; schema evolution leaving new key fields null in restored state; joining on a nullable column.

Related errors


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