{"record":{"id":"ddd597d6b507b258","repo":"apache/flink","slug":"concrete-subclass-of-tuple-expected","errorCode":null,"errorMessage":"Concrete subclass of Tuple expected.","messagePattern":"Concrete subclass of Tuple expected\\.","errorType":"exception","errorClass":"InvalidTypesException","httpStatus":null,"severity":"error","filePath":"flink-core/src/main/java/org/apache/flink/api/java/typeutils/TypeExtractor.java","lineNumber":1539,"sourceCode":"                    throw new InvalidTypesException(\"SQL time type expected.\");\n                }\n                // check if correct SQL time type\n                if (!typeInfo.equals(actual)) {\n                    throw new InvalidTypesException(\n                            \"SQL time type '\" + typeInfo + \"' expected but was '\" + actual + \"'.\");\n                }\n\n            }\n            // check for Java Tuples\n            else if (typeInfo instanceof TupleTypeInfo) {\n                // check if tuple at all\n                if (!(isClassType(type) && Tuple.class.isAssignableFrom(typeToClass(type)))) {\n                    throw new InvalidTypesException(\"Tuple type expected.\");\n                }\n\n                // do not allow usage of Tuple as type\n                if (isClassType(type) && typeToClass(type).equals(Tuple.class)) {\n                    throw new InvalidTypesException(\"Concrete subclass of Tuple expected.\");\n                }\n\n                // go up the hierarchy until we reach immediate child of Tuple (with or without\n                // generics)\n                while (!(isClassType(type)\n                        && typeToClass(type).getSuperclass().equals(Tuple.class))) {\n                    typeHierarchy.add(type);\n                    type = typeToClass(type).getGenericSuperclass();\n                }\n\n                if (type == Tuple0.class) {\n                    return;\n                }\n\n                // check if immediate child of Tuple has generics\n                if (type instanceof Class<?>) {\n                    throw new InvalidTypesException(\"Parameterized Tuple type expected.\");\n                }","sourceCodeStart":1521,"sourceCodeEnd":1557,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/api/java/typeutils/TypeExtractor.java#L1521-L1557","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before — raw Tuple\npublic class MyFunc extends MapFunction<Tuple, String> { ... }\n\n// after — concrete Tuple subclass\npublic class MyFunc extends MapFunction<Tuple2<String, Integer>, String> {\n    public String map(Tuple2<String, Integer> value) { ... }\n}","handlingStrategy":"validation","validationCode":"// Check that the function does not use raw Tuple as input type\nClass<?> funcInputClass = myFunctionInputClass;\nif (Tuple.class.equals(funcInputClass)) {\n    throw new IllegalArgumentException(\n        \"Raw Tuple cannot be used as a type. \"\n        + \"Use a concrete subclass like Tuple2<String, Integer>.\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["type-validation","tuple","raw-type","type-mismatch","reflection"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}