apache/flink · error · InvalidTypesException

SQL time type '{}' expected but was '{}'.

Error message

SQL time type '{}' expected but was '{}'.

What it means

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.

Source

Thrown at flink-core/src/main/java/org/apache/flink/api/java/typeutils/TypeExtractor.java:1525

                // check if correct basic type
                if (!typeInfo.equals(actual)) {
                    throw new InvalidTypesException(
                            "Basic type '" + typeInfo + "' expected but was '" + actual + "'.");
                }

            }
            // check for Java SQL time types
            else if (typeInfo instanceof SqlTimeTypeInfo) {

                TypeInformation<?> actual;
                // check if SQL time type at all
                if (!(type instanceof Class<?>)
                        || (actual = SqlTimeTypeInfo.getInfoFor((Class<?>) type)) == null) {
                    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)

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Align the function's temporal type parameter with the DataStream's element type
  2. Add a conversion step to transform between SQL temporal types
  3. Standardize on one SQL temporal type throughout the pipeline

Example fix

// before — Timestamp vs Date mismatch
DataStream<java.sql.Date> stream = ...;
stream.map(new MapFunction<java.sql.Timestamp, X>() { ... });

// after — align types
stream.map(date -> new java.sql.Timestamp(date.getTime()))
      .map(new MapFunction<java.sql.Timestamp, X>() { ... });
Defensive patterns

Strategy: validation

Validate before calling

// Verify SQL time types match
TypeInformation<?> streamType = stream.getType();
if (streamType instanceof SqlTimeTypeInfo) {
    SqlTimeTypeInfo<?> sqlType = (SqlTimeTypeInfo<?>) streamType;
    // Ensure function input matches
    Class<?> funcInputClass = java.sql.Timestamp.class; // from function signature
    if (!sqlType.getTypeClass().equals(funcInputClass)) {
        throw new IllegalStateException(
            "SQL time mismatch: stream has " + sqlType.getTypeClass()
            + " but function expects " + funcInputClass);
    }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/7c8fc9b5f3a20ef7. Report an issue: GitHub.