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
- Use a concrete Tuple subclass: `Tuple2<String, Integer>` instead of raw `Tuple`
- If the arity varies, use a POJO or Row instead of Tuple
- 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
- Never use raw `Tuple` as a type parameter — always specify a concrete subclass
- Use Tuple0 for empty tuples if needed
- Use IDE inspections to catch raw type usage
- Prefer POJOs or Row for schemas that need flexibility in arity
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
- Tuple type expected.
- Parameterized Tuple type expected.
- Tuple arity '{}' expected but was '{}'.
- Basic type expected.
- Basic type '{}' expected but was '{}'.
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/ddd597d6b507b258.
Report an issue: GitHub.