apache/flink · error · InvalidTypesException
POJO type '{}' expected but was '{}'.
Error message
POJO type '{}' expected but was '{}'. What it means
Thrown by TypeExtractor.validateInfo when a PojoTypeInfo is expected but the reflected type's class does not exactly match the PojoTypeInfo's type class. This means the type extractor expected a specific POJO class but found a different class through reflection.
Source
Thrown at flink-core/src/main/java/org/apache/flink/api/java/typeutils/TypeExtractor.java:1673
if (!(type instanceof Class<?> && Value.class.isAssignableFrom((Class<?>) type))) {
throw new InvalidTypesException("Value type expected.");
}
TypeInformation<?> actual;
// check value type contents
if (!typeInfo.equals(
actual = ValueTypeInfo.getValueTypeInfo((Class<? extends Value>) type))) {
throw new InvalidTypesException(
"Value type '" + typeInfo + "' expected but was '" + actual + "'.");
}
}
// check for POJO
else if (typeInfo instanceof PojoTypeInfo) {
Class<?> clazz = null;
if (!(isClassType(type)
&& ((PojoTypeInfo<?>) typeInfo).getTypeClass()
== (clazz = typeToClass(type)))) {
throw new InvalidTypesException(
"POJO type '"
+ ((PojoTypeInfo<?>) typeInfo).getTypeClass().getCanonicalName()
+ "' expected but was '"
+ clazz.getCanonicalName()
+ "'.");
}
}
// check for Enum
else if (typeInfo instanceof EnumTypeInfo) {
if (!(type instanceof Class<?> && Enum.class.isAssignableFrom((Class<?>) type))) {
throw new InvalidTypesException("Enum type expected.");
}
// check enum type contents
if (!(typeInfo.getTypeClass() == type)) {
throw new InvalidTypesException(
"Enum type '"
+ typeInfo.getTypeClass().getCanonicalName()
+ "' expected but was '"View on GitHub (pinned to 2f3c205e92)
Solutions
- Ensure the actual runtime class matches the declared PojoTypeInfo class exactly.
- Provide explicit TypeInformation via .returns(TypeInformation.of(MyPojo.class)) matching the actual class.
- If using inheritance, register the correct concrete POJO class, not the parent.
- Check for stale type hints after class refactoring.
Example fix
// before .returns(TypeInformation.of(ParentPojo.class)) // but actual is ChildPojo // after .returns(TypeInformation.of(ChildPojo.class))
Defensive patterns
Strategy: validation
Validate before calling
// Check POJO class match before extraction
Class<?> expectedClass = ((PojoTypeInfo<?>) typeInfo).getTypeClass();
Class<?> actualClass = typeToClass(type);
if (expectedClass != actualClass) {
// provide correct PojoTypeInfo
ti = TypeInformation.of(actualClass);
} Type guard
static boolean pojoClassesMatch(TypeInformation<?> expected, Type actual) {
return expected instanceof PojoTypeInfo<?>
&& isClassType(actual)
&& ((PojoTypeInfo<?>) expected).getTypeClass() == typeToClass(actual);
} Try / catch
try {
validateInfo(hierarchy, type, pojoTypeInfo);
} catch (InvalidTypesException e) {
ti = TypeInformation.of(typeToClass(type));
} Prevention
- Ensure the declared POJO class exactly matches the actual class.
- Provide explicit TypeInformation matching the concrete POJO class.
- Update type hints after refactoring POJO classes.
When it happens
Trigger: Called during validateInfo when TypeInformation is a PojoTypeInfo and either the type is not a ClassType, or typeToClass(type) differs from the PojoInfo's getTypeClass(). Occurs when the declared POJO type class does not match the actual generic type argument resolved by reflection.
Common situations: Using a subclass of a POJO where the parent was expected, or vice versa. Generic functions where the POJO class is parameterized and erasure resolves to a different class. Refactoring POJO classes (renaming/moving) without updating type hints or serialized state.
Related errors
- Enum type '{}' expected but was '{}'.
- Generic type '{}' or a subclass of it expected but was '{}'.
- POJO type expected but was: {}
- Object array type expected.
- Value type expected.
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/44831e520ab654d5.
Report an issue: GitHub.