apache/flink · error · InvalidTypesException
The field {} is already contained in the hierarchy of the {}
Error message
The field {} is already contained in the hierarchy of the {}.Please use unique field names through your classes hierarchy What it means
Thrown by TypeExtractor.getAllDeclaredFields when traversing a class hierarchy and encountering two non-static, non-transient fields with the same name in different levels of the hierarchy (e.g., a field declared in both a class and its superclass). Flink requires unique field names across the entire POJO hierarchy to avoid ambiguity during serialization and field access.
Source
Thrown at flink-core/src/main/java/org/apache/flink/api/java/typeutils/TypeExtractor.java:2304
* @param ignoreDuplicates if true, in case of duplicate field names only the lowest one in a
* hierarchy will be returned; throws an exception otherwise
* @return list of fields
*/
@PublicEvolving
public static List<Field> getAllDeclaredFields(Class<?> clazz, boolean ignoreDuplicates) {
List<Field> result = new ArrayList<>();
while (clazz != null) {
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (Modifier.isTransient(field.getModifiers())
|| Modifier.isStatic(field.getModifiers())) {
continue; // we have no use for transient or static fields
}
if (hasFieldWithSameName(field.getName(), result)) {
if (ignoreDuplicates) {
continue;
} else {
throw new InvalidTypesException(
"The field "
+ field
+ " is already contained in the hierarchy of the "
+ clazz
+ "."
+ "Please use unique field names through your classes hierarchy");
}
}
result.add(field);
}
clazz = clazz.getSuperclass();
}
return result;
}
@PublicEvolving
public static Field getDeclaredField(Class<?> clazz, String name) {
for (Field field : getAllDeclaredFields(clazz, true)) {View on GitHub (pinned to 2f3c205e92)
Solutions
- Rename the field in the subclass or superclass so all field names are unique across the hierarchy.
- Remove the duplicate field declaration in the subclass if the parent field is sufficient.
- If you cannot change the class hierarchy, consider using getAllDeclaredFields(clazz, true) to ignore duplicates (lowest wins), or annotate with @TypeInfo to provide custom type info.
- Mark the duplicate field as transient or static if it should not participate in serialization.
Example fix
// before
class Base {
private String name;
}
class Child extends Base {
private String name; // duplicate!
}
// after
class Base {
private String name;
}
class Child extends Base {
private String childName; // unique
} Defensive patterns
Strategy: validation
Validate before calling
// Before type extraction, check for duplicate field names
List<Field> allFields = getAllDeclaredFields(clazz, true); // ignore dups to probe
Set<String> names = new HashSet<>();
for (Field f : allFields) {
if (!names.add(f.getName())) {
// duplicate field name detected across hierarchy
}
} Type guard
static boolean hasUniqueFieldNames(Class<?> clazz) {
Set<String> seen = new HashSet<>();
Class<?> c = clazz;
while (c != null) {
for (Field f : c.getDeclaredFields()) {
if (Modifier.isTransient(f.getModifiers()) || Modifier.isStatic(f.getModifiers())) continue;
if (!seen.add(f.getName())) return false;
}
c = c.getSuperclass();
}
return true;
} Try / catch
try {
List<Field> fields = getAllDeclaredFields(clazz, false);
} catch (InvalidTypesException e) {
// fall back: ignore duplicates (lowest in hierarchy wins)
fields = getAllDeclaredFields(clazz, true);
} Prevention
- Avoid field shadowing: never redeclare a field name that exists in a superclass.
- Use unique field names across the entire class hierarchy.
- Mark non-serializable duplicate fields as transient or static.
- Consider composition over inheritance to avoid field name collisions.
When it happens
Trigger: Called during getAllDeclaredFields(clazz, false) when a class hierarchy contains two or more fields with identical names (e.g., a field 'id' in both a subclass and its parent class), and ignoreDuplicates is false. This is triggered during POJO analysis when the type extractor walks the class hierarchy.
Common situations: A POJO subclass that redeclares a field already present in its superclass (field shadowing). Lombok-generated fields that collide with manually declared parent fields. JPA entity hierarchies where @Id fields are redeclared. Using third-party base classes with fields that conflict with your subclass fields.
Related errors
- POJO type expected but was: {}
- POJO type '{}' expected but was '{}'.
- The given class is no subclass of {Writable.class.getName()}
- Cannot register null type class.
- Tuple type expected but was: {}
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/9fd46d42a870b073.
Report an issue: GitHub.