apache/flink · error · InvalidFieldReferenceException

Invalid tuple field reference "{}".

Error message

Invalid tuple field reference "{}".

What it means

Thrown by TupleTypeInfoBase.getFlatFields when the fieldExpression does not match the tuple field regex. Tuple fields are addressed as 'f0', 'f1', ..., or bare integers '0', '1', ... (optionally dotted with a nested tail), or '*'/'_' wildcards. Any other syntax fails. This is an InvalidFieldReferenceException.

Source

Thrown at flink-core/src/main/java/org/apache/flink/api/java/typeutils/TupleTypeInfoBase.java:105

    }

    /** Returns the field types. */
    public TypeInformation<?>[] getFieldTypes() {
        return types;
    }

    @Override
    public int getTotalFields() {
        return totalFields;
    }

    @Override
    public void getFlatFields(
            String fieldExpression, int offset, List<FlatFieldDescriptor> result) {

        Matcher matcher = PATTERN_NESTED_FIELDS_WILDCARD.matcher(fieldExpression);
        if (!matcher.matches()) {
            throw new InvalidFieldReferenceException(
                    "Invalid tuple field reference \"" + fieldExpression + "\".");
        }

        String field = matcher.group(0);
        if (field.equals(ExpressionKeys.SELECT_ALL_CHAR)
                || field.equals(ExpressionKeys.SELECT_ALL_CHAR_SCALA)) {
            // handle select all
            int keyPosition = 0;
            for (TypeInformation<?> type : types) {
                if (type instanceof CompositeType) {
                    CompositeType<?> cType = (CompositeType<?>) type;
                    cType.getFlatFields(
                            String.valueOf(ExpressionKeys.SELECT_ALL_CHAR),
                            offset + keyPosition,
                            result);
                    keyPosition += cType.getTotalFields() - 1;
                } else {
                    result.add(new FlatFieldDescriptor(offset + keyPosition, type));

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Use tuple field syntax: 'f0', 'f1', ... or bare integers '0', '1', ....
  2. For nested access use 'f0.subField' or '0.subField'.
  3. Use '*' or '_' for all fields.

Example fix

// before
tupleStream.keyBy("myField"); // Tuple2<String, Integer> has no 'myField'
// after
tupleStream.keyBy("f0");
Defensive patterns

Strategy: validation

Validate before calling

private static final Pattern TUPLE_FIELD =
    Pattern.compile("(f?)([0-9]+)(\\\.(.+))?");

void validateTupleFieldExpr(String expr) {
    if (expr == null || !TUPLE_FIELD.matcher(expr).matches()) {
        throw new IllegalArgumentException(
            "Invalid tuple field expression: " + expr);
    }
}

Prevention

When it happens

Trigger: Calling tupleType.getFlatFields("name") (tuples use f0/f1 not arbitrary names), getFlatFields("f"), getFlatFields(""), or getFlatFields("f0."). Also reached via keyBy("myField") on a Tuple-typed stream where the developer used POJO-style naming.

Common situations: Developer confuses Tuple field syntax (f0, f1) with POJO/Row field syntax (named fields). Common when switching from POJO to Tuple types without updating key expressions. Also triggered by passing empty strings or strings with invalid characters.

Related errors


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