apache/flink · error · IncompatibleKeysException

The number of specified keys is different.

Error message

The number of specified keys is different.

What it means

Thrown by Keys.areCompatible() as IncompatibleKeysException(SIZE_MISMATCH_MESSAGE) when two key specifications declare a different number of key fields. Flink requires join/coGroup/group keys on both sides to have matching arity so the runtime can pair key fields positionally; a size mismatch means the two sides cannot be key-aligned.

Source

Thrown at flink-core/src/main/java/org/apache/flink/api/common/operators/Keys.java:66

    public abstract TypeInformation<?>[] getKeyFieldTypes();

    public abstract TypeInformation<?>[] getOriginalKeyFieldTypes();

    public abstract <E> void validateCustomPartitioner(
            Partitioner<E> partitioner, TypeInformation<E> typeInfo);

    public boolean isEmpty() {
        return getNumberOfKeyFields() == 0;
    }

    /** Check if two sets of keys are compatible to each other (matching types, key counts) */
    public boolean areCompatible(Keys<?> other) throws IncompatibleKeysException {

        TypeInformation<?>[] thisKeyFieldTypes = this.getKeyFieldTypes();
        TypeInformation<?>[] otherKeyFieldTypes = other.getKeyFieldTypes();

        if (thisKeyFieldTypes.length != otherKeyFieldTypes.length) {
            throw new IncompatibleKeysException(IncompatibleKeysException.SIZE_MISMATCH_MESSAGE);
        } else {
            for (int i = 0; i < thisKeyFieldTypes.length; i++) {
                if (!thisKeyFieldTypes[i].equals(otherKeyFieldTypes[i])) {
                    throw new IncompatibleKeysException(
                            thisKeyFieldTypes[i], otherKeyFieldTypes[i]);
                }
            }
        }
        return true;
    }

    // --------------------------------------------------------------------------------------------
    //  Specializations for expression-based / extractor-based grouping
    // --------------------------------------------------------------------------------------------

    public static class SelectorFunctionKeys<T, K> extends Keys<T> {

        private final KeySelector<T, K> keyExtractor;

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Make the number of key fields identical on both sides of where(...) and equalTo(...).
  2. If the keys are semantically the same but split across fields, wrap one side in a KeySelector returning a composite key matching the other side's arity.
  3. Re-read the stack trace to confirm which pair of key specs disagree (left vs right).

Example fix

// before
dsA.join(dsB).where(0, 1).equalTo(0);
// after
dsA.join(dsB).where(0, 1).equalTo(0, 1);
Defensive patterns

Strategy: validation

Validate before calling

int[] left = ...; int[] right = ...;
if (left.length != right.length) {
    throw new IllegalArgumentException(
        "Join key arity mismatch: " + left.length + " vs " + right.length);
}

Try / catch

try {
    a.join(b).where(leftKeys).equalTo(rightKeys);
} catch (Exception e) {
    if (e.getCause() instanceof Keys.IncompatibleKeysException) { /* fix key arity */ }
    throw e;
}

Prevention

When it happens

Trigger: Calling datasetA.join(datasetB).where(0,1).equalTo(0) (2 key fields vs 1); mixing a tuple-position key with a KeySelector returning a single-field type in a join; using different key expressions on left and right of a coGroup.

Common situations: Joining two DataSets with mismatched key arity (e.g. .where(0,1).equalTo(0)); evolving one side's schema to add a key field without updating the other; copy-paste of join declarations with a different field count.

Related errors


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