apache/flink · error · InvalidTypesException
Enum type '{}' expected but was '{}'.
Error message
Enum type '{}' expected but was '{}'. What it means
Thrown by TypeExtractor.validateInfo when an EnumTypeInfo is expected, the type is an Enum, but the expected enum class differs from the actual enum class found by reflection. This indicates a mismatch between two specific enum types.
Source
Thrown at flink-core/src/main/java/org/apache/flink/api/java/typeutils/TypeExtractor.java:1688
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 '"
+ typeToClass(type).getCanonicalName()
+ "'.");
}
}
// check for generic object
else if (typeInfo instanceof GenericTypeInfo<?>) {
Class<?> clazz = null;
if (!(isClassType(type)
&& (clazz = typeToClass(type))
.isAssignableFrom(
((GenericTypeInfo<?>) typeInfo).getTypeClass()))) {
throw new InvalidTypesException(
"Generic type '"
+ ((GenericTypeInfo<?>) typeInfo)
.getTypeClass()View on GitHub (pinned to 2f3c205e92)
Solutions
- Align the declared EnumTypeInfo with the actual enum class used at runtime.
- Provide the correct explicit TypeInformation via .returns(TypeInformation.of(ActualEnum.class)).
- Check for accidental enum substitution (e.g., StatusEnum vs ColorEnum).
- Update type hints after enum refactoring.
Example fix
// before .returns(TypeInformation.of(OldStatusEnum.class)) // actual is NewStatusEnum // after .returns(TypeInformation.of(NewStatusEnum.class))
Defensive patterns
Strategy: validation
Validate before calling
// Check that the expected enum class matches the actual
Class<?> expectedEnum = typeInfo.getTypeClass();
Class<?> actualEnum = (Class<?>) type;
if (expectedEnum != actualEnum) {
// align enum types
ti = TypeInformation.of(actualEnum);
} Type guard
static boolean enumClassesMatch(EnumTypeInfo<?> expected, Class<?> actual) {
return expected.getTypeClass() == actual;
} Try / catch
try {
validateInfo(hierarchy, type, enumTypeInfo);
} catch (InvalidTypesException e) {
ti = TypeInformation.of((Class<?>) type);
} Prevention
- Align declared EnumTypeInfo with the actual enum class.
- Avoid substituting one enum for another in generic positions.
- Update type hints after refactoring enum types.
When it happens
Trigger: Called during validateInfo after confirming the type is an Enum, but typeInfo.getTypeClass() != type (the actual class). Occurs when the declared EnumTypeInfo references one enum but the reflected type argument resolves to a different enum class.
Common situations: Generic UDFs where different enum types are used in the declared vs actual positions. Refactoring enum types (renaming/moving) without updating type hints. Using a parent or related enum type where a specific one was declared.
Related errors
- POJO type '{}' expected but was '{}'.
- Enum type expected.
- Generic type '{}' or a subclass of it 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/8db2d848235b3786.
Report an issue: GitHub.