apache/flink · error · KeyFieldOutOfBoundsException

{}

Error message

{}

What it means

RowComparator.hash() iterates the configured key positions and calls record.getField(keyPositions[i]) on each. If a key position index is beyond the Row's arity (number of fields), Row.getField raises IndexOutOfBoundsException, which is caught and re-thrown as KeyFieldOutOfBoundsException with the message 'Field N is accessed for a key, but out of bounds in the record.' The comparator and the Row disagree on how many fields the Row has.

Source

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

    public void getFlatComparator(List<TypeComparator> flatComparators) {
        for (NullAwareComparator<Object> c : comparators) {
            Collections.addAll(flatComparators, c.getFlatComparators());
        }
    }

    @Override
    public int hash(Row record) {
        int code = 0;
        int i = 0;

        try {
            for (; i < keyPositions.length; i++) {
                code *= TupleComparatorBase.HASH_SALT[i & 0x1F];
                Object element = record.getField(keyPositions[i]); // element can be null
                code += comparators[i].hash(element);
            }
        } catch (IndexOutOfBoundsException e) {
            throw new KeyFieldOutOfBoundsException(keyPositions[i]);
        }

        return code;
    }

    @Override
    public void setReference(Row toCompare) {
        int i = 0;
        try {
            for (; i < keyPositions.length; i++) {
                TypeComparator<Object> comparator = comparators[i];
                Object element = toCompare.getField(keyPositions[i]);
                comparator.setReference(element); // element can be null
            }
        } catch (IndexOutOfBoundsException e) {
            throw new KeyFieldOutOfBoundsException(keyPositions[i]);
        }
    }

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Align the key position indices with the actual Row arity — verify Row.getArity() matches the comparator's expected arity before the operation.
  2. If you changed the Row schema, update the key specification (keyBy / sort / groupBy field indices) to reference valid positions.
  3. Trace the upstream operator that produces the Row and confirm its output arity; add an arity check in a MapFunction if needed.
  4. If restoring from a savepoint with a schema mismatch, implement a state migration or start from a clean savepoint.

Example fix

// before — comparator keys on position 2 but Rows only have 2 fields (indices 0,1)
dataSet.sortPartition(2, Order.ASCENDING); // Row arity = 2 → IOOBE

// after — key on a valid position within the Row's arity
dataSet.sortPartition(1, Order.ASCENDING); // valid: index 1 < arity 2
Defensive patterns

Strategy: validation

Validate before calling

// Before hashing or keying a Row, validate all key positions are in bounds
public static void validateKeyPositions(Row row, int[] keyPositions) {
    for (int pos : keyPositions) {
        if (pos < 0 || pos >= row.getArity()) {
            throw new IllegalArgumentException(
                "Key position " + pos + " is out of bounds for Row arity " + row.getArity());
        }
    }
}

Try / catch

try {
    int hash = comparator.hash(record);
} catch (KeyFieldOutOfBoundsException e) {
    log.error("Row arity {} too small for key position {}",
        record.getArity(), e.getFieldNumber());
    throw e;
}

Prevention

When it happens

Trigger: The RowComparator is configured with keyPositions referencing field indices that the actual Row at runtime does not contain — e.g., comparator keys on position 3 but the Row only has 2 fields. This arises when the comparator's arity assumption diverges from the data's actual arity.

Common situations: The Row schema was changed (fields added or removed) without updating the key specification; a keyBy / sort uses positional indices computed against one schema but the upstream operator emits Rows with a different arity; a DataSet groupBy/sort with key positions [0,1,2] receives Rows of arity 2 due to a projection that was added without updating keys; legacy savepoint data with an older Row arity restored into a job whose comparator expects more fields.

Related errors


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