apache/flink · error · InvalidTypesException

Basic type '{}' expected but was '{}'.

Error message

Basic type '{}' expected but was '{}'.

What it means

Thrown during input type validation when both the expected and actual types are BasicTypeInfo, but they do not match. The function declares one basic type (e.g. Integer) in its signature but the DataStream's TypeInformation represents a different basic type (e.g. String). This is a type-safety check to catch incompatible basic type assignments before runtime serialization errors.

Source

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

        }

        if (typeInfo == null) {
            throw new InvalidTypesException("Unknown Error. TypeInformation is null.");
        }

        if (!(type instanceof TypeVariable<?>)) {
            // check for Java Basic Types
            if (typeInfo instanceof BasicTypeInfo) {

                TypeInformation<?> actual;
                // check if basic type at all
                if (!(type instanceof Class<?>)
                        || (actual = BasicTypeInfo.getInfoFor((Class<?>) type)) == null) {
                    throw new InvalidTypesException("Basic type expected.");
                }
                // 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 + "'.");
                }

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Align the function's input type parameter with the DataStream's element type
  2. Add a conversion map to transform the stream element type before the function
  3. Fix the function signature to declare the correct input basic type

Example fix

// before — type mismatch
DataStream<Integer> counts = ...;
counts.map(new MapFunction<String, String>() { ... }); // expects String, got Integer

// after — align types
counts.map(new MapFunction<Integer, String>() {
    public String map(Integer value) { return value.toString(); }
});
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check that basic types match
TypeInformation<?> streamType = stream.getType();
TypeInformation<?> funcInputType = TypeInformation.of(Integer.class);
if (streamType instanceof BasicTypeInfo
        && funcInputType instanceof BasicTypeInfo
        && !streamType.equals(funcInputType)) {
    throw new IllegalStateException(
        "Type mismatch: stream has " + streamType + " but function expects " + funcInputType);
}

Prevention

When it happens

Trigger: A function signature says `MapFunction<String, X>` but the DataStream carries `DataStream<Integer>`. Both are basic types, but they are different basic types. The `typeInfo.equals(actual)` check fails, producing this error with both type names.

Common situations: Refactoring a pipeline to change element types without updating function signatures. Mixing up column orders or field types in a transformation chain. Connecting operators designed for different basic types.

Related errors


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