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.
Solutions
- Parameterize the Tuple subclass with explicit field types: `class Event extends Tuple2<String, Long> {}`
- If using the DataStream API, supply the TypeInformation explicitly via `.returns(TypeInformation.of(new TypeHint<Tuple2<String,Long>>(){}))`
- Implement ResultTypeQueryable on the function and override getProducedType() to return the TypeInformation manually
- 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
- Always specify type parameters when subclassing Tuple: `extends Tuple2<String, Long>`
- Use Flink's Tuple0 for empty tuples if needed
- Prefer POJOs or Row for complex data models to avoid Tuple parameterization issues
- Run a quick unit test calling TypeExtractor.createTypeInfo(MyClass.class) early in development
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
- Cannot convert type to class
- Parameterized Tuple type expected.
- The types of the interface
- Automatic type extraction is not possible on candidates…
- Cannot extract the type argument with index
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/c7730c088f3e99e1.
Report an issue: GitHub.
Appendix: 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)