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
- Align the function's input type parameter with the DataStream's element type
- Add a conversion map to transform the stream element type before the function
- 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
- Always verify that the DataStream's element type matches the function's declared input type
- Use type-safe builders or wrappers that check at compile time when possible
- Add a conversion map between incompatible basic types before the function
- Run integration tests that exercise the full pipeline to catch type mismatches early
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
- Basic type expected.
- SQL time type expected.
- SQL time type '{}' expected but was '{}'.
- Tuple type expected.
- Concrete subclass of Tuple expected.
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/64d852725a1c12bc.
Report an issue: GitHub.