{"record":{"id":"7c8fc9b5f3a20ef7","repo":"apache/flink","slug":"sql-time-type-expected-but-was","errorCode":null,"errorMessage":"SQL time type '{}' expected but was '{}'.","messagePattern":"SQL time type '(.+?)' expected but was '(.+?)'\\.","errorType":"exception","errorClass":"InvalidTypesException","httpStatus":null,"severity":"error","filePath":"flink-core/src/main/java/org/apache/flink/api/java/typeutils/TypeExtractor.java","lineNumber":1525,"sourceCode":"                // check if correct basic type\n                if (!typeInfo.equals(actual)) {\n                    throw new InvalidTypesException(\n                            \"Basic type '\" + typeInfo + \"' expected but was '\" + actual + \"'.\");\n                }\n\n            }\n            // check for Java SQL time types\n            else if (typeInfo instanceof SqlTimeTypeInfo) {\n\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)","sourceCodeStart":1507,"sourceCodeEnd":1543,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/api/java/typeutils/TypeExtractor.java#L1507-L1543","documentation":"Thrown during input type validation when the TypeInformation is SqlTimeTypeInfo but the reflected Type resolves to a different SQL time type than expected. For example, the stream carries Timestamp but the function expects Time. The `typeInfo.equals(actual)` check fails, producing this error with both type names.","triggerScenarios":"A function declares `MapFunction<java.sql.Timestamp, X>` but the DataStream carries `java.sql.Date` or `java.sql.Time`. Both are SqlTimeTypeInfo, but they are different SQL temporal types. The equality check fails.","commonSituations":"Swapping Date/Time/Timestamp types in a pipeline refactor. Connecting a JDBC source emitting Timestamp to a function expecting Time. Inconsistent temporal type usage across operators.","solutions":["Align the function's temporal type parameter with the DataStream's element type","Add a conversion step to transform between SQL temporal types","Standardize on one SQL temporal type throughout the pipeline"],"exampleFix":"// before — Timestamp vs Date mismatch\nDataStream<java.sql.Date> stream = ...;\nstream.map(new MapFunction<java.sql.Timestamp, X>() { ... });\n\n// after — align types\nstream.map(date -> new java.sql.Timestamp(date.getTime()))\n      .map(new MapFunction<java.sql.Timestamp, X>() { ... });","handlingStrategy":"validation","validationCode":"// Verify SQL time types match\nTypeInformation<?> streamType = stream.getType();\nif (streamType instanceof SqlTimeTypeInfo) {\n    SqlTimeTypeInfo<?> sqlType = (SqlTimeTypeInfo<?>) streamType;\n    // Ensure function input matches\n    Class<?> funcInputClass = java.sql.Timestamp.class; // from function signature\n    if (!sqlType.getTypeClass().equals(funcInputClass)) {\n        throw new IllegalStateException(\n            \"SQL time mismatch: stream has \" + sqlType.getTypeClass()\n            + \" but function expects \" + funcInputClass);\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Standardize on one SQL temporal type throughout the pipeline","Add explicit conversion steps between Date, Time, and Timestamp when needed","Document the expected temporal type in function JavaDoc","Use unit tests to verify temporal type compatibility between operators"],"tags":["type-validation","sql-time","type-mismatch","reflection","temporal"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}