apache/flink · error · InvalidTypesException

Tuple needs to be parameterized by using generics.

Error message

Tuple needs to be parameterized by using generics.

What it means

Thrown when Flink's TypeExtractor encounters a Tuple subclass that is used as a raw type without type parameters. The extractor walks the class hierarchy up to the immediate child of Tuple and checks whether that child is a ParameterizedType; if it is a plain Class instead, the generic field types of the tuple have been erased and cannot be recovered. This makes serialization and state management impossible, so extraction fails.

Source

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

                        "Usage of class Tuple as a type is not allowed. Use a concrete subclass (e.g. Tuple1, Tuple2, etc.) instead.");
            }

            // go up the hierarchy until we reach immediate child of Tuple (with or without
            // generics)
            // collect the types while moving up for a later top-down
            List<Type> typeHierarchyForSubtypes = new ArrayList<>(typeHierarchy);
            while (!(isClassType(curT) && typeToClass(curT).getSuperclass().equals(Tuple.class))) {
                typeHierarchyForSubtypes.add(curT);
                curT = typeToClass(curT).getGenericSuperclass();
            }

            if (curT == Tuple0.class) {
                return new TupleTypeInfo(Tuple0.class);
            }

            // check if immediate child of Tuple has generics
            if (curT instanceof Class<?>) {
                throw new InvalidTypesException(
                        "Tuple needs to be parameterized by using generics.");
            }

            typeHierarchyForSubtypes.add(curT);

            // create the type information for the subtypes
            final TypeInformation<?>[] subTypesInfo =
                    createSubTypesInfo(
                            t,
                            (ParameterizedType) curT,
                            typeHierarchyForSubtypes,
                            in1Type,
                            in2Type,
                            false);
            // type needs to be treated a pojo due to additional fields
            if (subTypesInfo == null) {
                return analyzePojo(t, new ArrayList<>(typeHierarchy), in1Type, in2Type);
            }

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Parameterize the Tuple subclass with explicit field types: `class Event extends Tuple2<String, Long> {}`
  2. If using the DataStream API, supply the TypeInformation explicitly via `.returns(TypeInformation.of(new TypeHint<Tuple2<String,Long>>(){}))`
  3. Implement ResultTypeQueryable on the function and override getProducedType() to return the TypeInformation manually
  4. Use a POJO or Row instead of a custom Tuple subclass when genericity is hard to express

Example fix

// before
class Event extends Tuple2 {}

// after
class Event extends Tuple2<String, Long> {
    public String getId() { return f0; }
    public long getTs() { return f1; }
}
Defensive patterns

Strategy: validation

Validate before calling

// Before using a Tuple subclass, verify it is parameterized
Class<?> tupleClass = MyTuple.class;
Type supertype = tupleClass.getGenericSuperclass();
if (!(supertype instanceof ParameterizedType) && tupleClass != Tuple0.class) {
    throw new IllegalArgumentException(
        "Tuple subclass " + tupleClass.getName()
        + " must be parameterized, e.g. extends Tuple2<String, Integer>");
}

Prevention

When it happens

Trigger: A subclass of Tuple (Tuple1–Tuple25) is used as a raw type — e.g. `class MyTuple extends Tuple2` without `<String,Integer>`. Occurs when a function returns or accepts a non-generic Tuple subclass, or when a Tuple subclass is defined without specifying its field types on the extends clause.

Common situations: Defining a custom Tuple subclass like `class Event extends Tuple2 {}` instead of `class Event extends Tuple2<String,Long> {}`. Using a raw Tuple subclass as a MapFunction output type. Subclassing a Tuple in legacy Java code that suppresses generics.

Related errors


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