apache/flink · error · InvalidProgramException

Unable to extract key from expression '{keyExpr}' on key {cT

Error message

Unable to extract key from expression '{keyExpr}' on key {cType}

What it means

Thrown by ExpressionKeys(String[], TypeInformation) when cType.getFlatFields(keyExpr) returns an empty list, i.e. the expression does not match any field on the composite type. The expression may be misspelled, reference a non-existent nested path, or target a field not present in the POJO/Tuple schema.

Source

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

            if (type instanceof CompositeType) {
                CompositeType<T> cType = (CompositeType<T>) type;
                this.originalKeyTypes = new TypeInformation<?>[keyExpressions.length];

                // extract the keys on their flat position
                for (int i = 0; i < keyExpressions.length; i++) {
                    String keyExpr = keyExpressions[i];

                    if (keyExpr == null) {
                        throw new InvalidProgramException("Expression key may not be null.");
                    }
                    // strip off whitespace
                    keyExpr = keyExpr.trim();

                    List<FlatFieldDescriptor> flatFields = cType.getFlatFields(keyExpr);

                    if (flatFields.size() == 0) {
                        throw new InvalidProgramException(
                                "Unable to extract key from expression '"
                                        + keyExpr
                                        + "' on key "
                                        + cType);
                    }
                    // check if all nested fields can be used as keys
                    for (FlatFieldDescriptor field : flatFields) {
                        if (!field.getType().isKeyType()) {
                            throw new InvalidProgramException(
                                    "This type (" + field.getType() + ") cannot be used as key.");
                        }
                    }
                    // add flat fields to key fields
                    keyFields.addAll(flatFields);

                    String strippedKeyExpr = WILD_CARD_REGEX.matcher(keyExpr).replaceAll("");
                    if (strippedKeyExpr.isEmpty()) {
                        this.originalKeyTypes[i] = type;

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Verify the field name exactly matches the POJO/Tuple field (case-sensitive for POJOs).
  2. For nested fields, confirm each path segment exists and is correctly named.
  3. Print the type's field names (cType.getFieldNames()) to compare against your expression.

Example fix

// before (POJO field is 'userId')
ds.groupBy("usrId");
// after
ds.groupBy("userId");
Defensive patterns

Strategy: validation

Validate before calling

List<FlatFieldDescriptor> resolved = cType.getFlatFields(keyExpr);
if (resolved.isEmpty()) {
    throw new IllegalArgumentException(
        "No field matches expression '" + keyExpr + "' on " + cType + ". Known fields: "
            + Arrays.toString(cType.getFieldNames()));
}

Type guard

static boolean fieldExists(CompositeType<?> t, String expr) {
    try { return !t.getFlatFields(expr).isEmpty(); }
    catch (Throwable x) { return false; }
}

Prevention

When it happens

Trigger: Calling groupBy("usrId") instead of groupBy("userId"); referencing a nested path like "address.zip" on a POJO whose address field has no zip; using a field name valid on one schema but not the runtime type.

Common situations: Typos in field-expression keys; schema drift where a field was renamed or removed; copy-pasting a key from a different dataset's schema; case-sensitivity mismatches on POJO field names.

Related errors


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