apache/flink · error · InvalidTypesException

Tuple type expected.

Error message

Tuple type expected.

What it means

Thrown during input type validation when the TypeInformation is TupleTypeInfo but the reflected Type is not a Tuple subclass. The check `Tuple.class.isAssignableFrom(typeToClass(type))` fails, meaning the function expects a Tuple input but the actual type in the function signature or the stream is not a Tuple at all.

Source

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

                TypeInformation<?> actual;
                // check if SQL time type at all
                if (!(type instanceof Class<?>)
                        || (actual = SqlTimeTypeInfo.getInfoFor((Class<?>) type)) == null) {
                    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;
                }

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Align the function's input type to be a Tuple subclass matching the stream's TupleTypeInfo
  2. If the stream carries a POJO, convert it to a Tuple before the function, or change the function to accept the POJO
  3. Use projection or mapping to transform the element type before the function

Example fix

// before — function expects POJO, stream carries Tuple
DataStream<Tuple2<String, Integer>> stream = ...;
stream.map(new MapFunction<MyEvent, X>() { ... });

// after — align to Tuple
stream.map(new MapFunction<Tuple2<String, Integer>, X>() {
    public X map(Tuple2<String, Integer> t) { ... }
});
Defensive patterns

Strategy: validation

Validate before calling

// Verify the function's input type is a Tuple subclass when stream carries TupleTypeInfo
if (stream.getType() instanceof TupleTypeInfo) {
    Class<?> funcInputClass = myFunctionInputClass; // from reflection
    if (!Tuple.class.isAssignableFrom(funcInputClass)) {
        throw new IllegalStateException(
            "Stream carries Tuple but function input "
            + funcInputClass.getName() + " is not a Tuple subclass");
    }
}

Prevention

When it happens

Trigger: A function or operator expects a Tuple as input (e.g. `MapFunction<Tuple2<String,Integer>, X>`) but the reflected type from the class hierarchy is a POJO, a basic type, or a non-Tuple class. Or the DataStream's TypeInformation is TupleTypeInfo but the function's declared input type is not a Tuple.

Common situations: Using keyBy() which produces Tuple-typed keys, then applying a function that expects a non-Tuple type. Connecting a Tuple-emitting source to a function designed for POJOs. Mismatch between projected fields (as Tuple) and the consuming function's type.

Related errors


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