{"record":{"id":"a0fc5c50d254aad8","repo":"apache/flink","slug":"tuple-type-expected","errorCode":null,"errorMessage":"Tuple type expected.","messagePattern":"Tuple type expected\\.","errorType":"exception","errorClass":"InvalidTypesException","httpStatus":null,"severity":"error","filePath":"flink-core/src/main/java/org/apache/flink/api/java/typeutils/TypeExtractor.java","lineNumber":1534,"sourceCode":"\n                TypeInformation<?> actual;\n                // check if SQL time type at all\n                if (!(type instanceof Class<?>)\n                        || (actual = SqlTimeTypeInfo.getInfoFor((Class<?>) type)) == null) {\n                    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                }","sourceCodeStart":1516,"sourceCodeEnd":1552,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/api/java/typeutils/TypeExtractor.java#L1516-L1552","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Align the function's input type to be a Tuple subclass matching the stream's TupleTypeInfo","If the stream carries a POJO, convert it to a Tuple before the function, or change the function to accept the POJO","Use projection or mapping to transform the element type before the function"],"exampleFix":"// before — function expects POJO, stream carries Tuple\nDataStream<Tuple2<String, Integer>> stream = ...;\nstream.map(new MapFunction<MyEvent, X>() { ... });\n\n// after — align to Tuple\nstream.map(new MapFunction<Tuple2<String, Integer>, X>() {\n    public X map(Tuple2<String, Integer> t) { ... }\n});","handlingStrategy":"validation","validationCode":"// Verify the function's input type is a Tuple subclass when stream carries TupleTypeInfo\nif (stream.getType() instanceof TupleTypeInfo) {\n    Class<?> funcInputClass = myFunctionInputClass; // from reflection\n    if (!Tuple.class.isAssignableFrom(funcInputClass)) {\n        throw new IllegalStateException(\n            \"Stream carries Tuple but function input \"\n            + funcInputClass.getName() + \" is not a Tuple subclass\");\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Match function input Tuple types to the stream's TupleTypeInfo","Use explicit projections with `.project()` to ensure Tuple structure alignment","Convert between POJOs and Tuples explicitly with map operators","Use keyBy() return types consistently with the consuming function's input"],"tags":["type-validation","tuple","type-mismatch","reflection"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}