apache/flink · error · InvalidTypesException

Concrete subclass of Tuple expected.

Error message

Concrete subclass of Tuple expected.

What it means

Thrown during input type validation when the reflected Type is exactly `Tuple.class` itself (the base class), not a concrete subclass like Tuple1, Tuple2, etc. Flink requires concrete Tuple subclasses because the arity (number of fields) is encoded in the class name. Using the raw Tuple base class as a type makes field extraction impossible.

Source

Thrown at flink-core/src/main/java/org/apache/flink/api/java/typeutils/TypeExtractor.java:1539

                    throw new InvalidTypesException("SQL time type expected.");
                }
                // check if correct SQL time type
                if (!typeInfo.equals(actual)) {
                    throw new InvalidTypesException(
                            "SQL time type '" + typeInfo + "' expected but was '" + actual + "'.");
                }

            }
            // check for Java Tuples
            else if (typeInfo instanceof TupleTypeInfo) {
                // check if tuple at all
                if (!(isClassType(type) && Tuple.class.isAssignableFrom(typeToClass(type)))) {
                    throw new InvalidTypesException("Tuple type expected.");
                }

                // do not allow usage of Tuple as type
                if (isClassType(type) && typeToClass(type).equals(Tuple.class)) {
                    throw new InvalidTypesException("Concrete subclass of Tuple expected.");
                }

                // go up the hierarchy until we reach immediate child of Tuple (with or without
                // generics)
                while (!(isClassType(type)
                        && typeToClass(type).getSuperclass().equals(Tuple.class))) {
                    typeHierarchy.add(type);
                    type = typeToClass(type).getGenericSuperclass();
                }

                if (type == Tuple0.class) {
                    return;
                }

                // check if immediate child of Tuple has generics
                if (type instanceof Class<?>) {
                    throw new InvalidTypesException("Parameterized Tuple type expected.");
                }

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Use a concrete Tuple subclass: `Tuple2<String, Integer>` instead of raw `Tuple`
  2. If the arity varies, use a POJO or Row instead of Tuple
  3. If you need polymorphic tuple handling, use `Object` with explicit TypeInformation

Example fix

// before — raw Tuple
public class MyFunc extends MapFunction<Tuple, String> { ... }

// after — concrete Tuple subclass
public class MyFunc extends MapFunction<Tuple2<String, Integer>, String> {
    public String map(Tuple2<String, Integer> value) { ... }
}
Defensive patterns

Strategy: validation

Validate before calling

// Check that the function does not use raw Tuple as input type
Class<?> funcInputClass = myFunctionInputClass;
if (Tuple.class.equals(funcInputClass)) {
    throw new IllegalArgumentException(
        "Raw Tuple cannot be used as a type. "
        + "Use a concrete subclass like Tuple2<String, Integer>.");
}

Prevention

When it happens

Trigger: A function declares `MapFunction<Tuple, X>` using the raw Tuple base class instead of a specific subclass like `Tuple2<String, Integer>`. The check `typeToClass(type).equals(Tuple.class)` succeeds, triggering this error.

Common situations: Writing a function that accepts `Tuple` generically without specifying arity. Copy-pasting from examples that use raw Tuple. Using a raw Tuple type as a variable type in a function signature.

Related errors


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