apache/flink · error · InvalidFieldReferenceException

Invalid tuple field reference "{}".

Error message

Invalid tuple field reference "{}".

What it means

Thrown by RowTypeInfo.getFlatFields when the fieldExpression does not match Row's field regex (which accepts integer indices like '0', string names like 'f0'/'userName', dotted nested expressions, or '*'/'_' wildcards). Note the message says 'tuple' — this is a legacy wording in the RowTypeInfo code. This is an InvalidFieldReferenceException.

Source

Thrown at flink-core/src/main/java/org/apache/flink/api/java/typeutils/RowTypeInfo.java:106

    }

    public RowTypeInfo(TypeInformation<?>[] types, String[] fieldNames) {
        super(Row.class, types);
        checkNotNull(fieldNames, "FieldNames should not be null.");
        checkArgument(
                types.length == fieldNames.length, "Number of field types and names is different.");
        checkArgument(!hasDuplicateFieldNames(fieldNames), "Field names are not unique.");

        this.fieldNames = Arrays.copyOf(fieldNames, fieldNames.length);
    }

    @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<?> fType : types) {
                if (fType instanceof CompositeType) {
                    CompositeType<?> cType = (CompositeType<?>) fType;
                    cType.getFlatFields(
                            ExpressionKeys.SELECT_ALL_CHAR, offset + keyPosition, result);
                    keyPosition += cType.getTotalFields() - 1;
                } else {
                    result.add(new FlatFieldDescriptor(offset + keyPosition, fType));
                }

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Use a valid Row field expression: integer index ('0'), default name ('f0'), custom name (valid identifier), or '*'.
  2. Ensure custom Row field names are valid identifiers matching [\p{L}_$][\p{L}\p{Digit}_$]*.
  3. For nested Row/POJO fields inside a Row, use dot-separated expressions.

Example fix

// before
rowType.getFlatFields("my-field");
// after
rowType.getFlatFields("myField");
Defensive patterns

Strategy: validation

Validate before calling

private static final Pattern ROW_FIELD =
    Pattern.compile("([0-9]+|[\\p{L}_$][\\p{L}\\p{Digit}_$]*)(\\\.(.+))?");

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

Prevention

When it happens

Trigger: Calling tableEnv or DataStream operations on a Row-typed stream with keyBy("field-name"), getFlatFields(""), or getFlatFields("a."). Row field names default to 'f0','f1',... unless a RowTypeInfo with custom names was constructed. Expressions with invalid characters like spaces or hyphens fail the pattern.

Common situations: Developer uses a hyphenated or space-containing field name, or passes an empty string. Also occurs when a Row has custom field names set via RowTypeInfo(types, names) but the key references a name that doesn't match the regex (e.g. a name with a dot). Confusingly the error message says 'tuple' not 'Row', which can mislead.

Related errors


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