apache/flink · error · InvalidTypesException
Field '{}' could not be accessed.
Error message
Field '{}' could not be accessed. What it means
Thrown by Types.POJO(Class, Map) when TypeExtractor.getDeclaredField(pojoClass, fieldName) returns null, meaning no field with the given name exists on the class (or any of its superclasses). The map key you supplied does not correspond to a real, reflectively-discoverable field.
Source
Thrown at flink-core/src/main/java/org/apache/flink/api/common/typeinfo/Types.java:338
* <p>The generic types for all fields of the POJO can be defined in a hierarchy of subclasses.
*
* <p>If Flink's type analyzer is unable to extract a POJO field, an {@link
* org.apache.flink.api.common.functions.InvalidTypesException} is thrown.
*
* <p><strong>Note:</strong> In most cases the type information of fields can be determined
* automatically, we recommend to use {@link Types#POJO(Class)}.
*
* @param pojoClass POJO class
* @param fields map of fields that map a name to type information. The map key is the name of
* the field and the value is its type.
*/
public static <T> TypeInformation<T> POJO(
Class<T> pojoClass, Map<String, TypeInformation<?>> fields) {
final List<PojoField> pojoFields = new ArrayList<>(fields.size());
for (Map.Entry<String, TypeInformation<?>> field : fields.entrySet()) {
final Field f = TypeExtractor.getDeclaredField(pojoClass, field.getKey());
if (f == null) {
throw new InvalidTypesException(
"Field '" + field.getKey() + "' could not be accessed.");
}
pojoFields.add(new PojoField(f, field.getValue()));
}
return new PojoTypeInfo<>(pojoClass, pojoFields);
}
/**
* Returns generic type information for any Java object. The serialization logic will use the
* general purpose serializer Kryo.
*
* <p>Generic types are black-boxes for Flink, but allow any object and null values in fields.
*
* <p>By default, serialization of this type is not very efficient. Please read the
* documentation about how to improve efficiency (namely by pre-registering classes).
*
* @param genericClass any Java classView on GitHub (pinned to 2f3c205e92)
Solutions
- Verify every key in the fields Map matches an actual declared field name (case-sensitive) on pojoClass or its superclasses.
- Check for typos, casing differences, or stale names after a refactor.
- If the field is private and only exposed via getters/setters, note that Types.POJO(Class, Map) uses getDeclaredField which requires the raw field to exist — make the field accessible or switch to Types.POJO(Class) which uses bean introspection.
- Write a quick reflection check: Arrays.stream(MyClass.class.getDeclaredFields()).map(Field::getName) to list valid names.
Example fix
// before — typo in field name
Map<String, TypeInformation<?>> fields = Map.of(
"usrname", Types.STRING // actual field is "username"
);
Types.POJO(User.class, fields); // throws: Field 'usrname' could not be accessed.
// after — correct field name
Map<String, TypeInformation<?>> fields = Map.of(
"username", Types.STRING
);
Types.POJO(User.class, fields); // ok Defensive patterns
Strategy: validation
Validate before calling
// Verify field names exist before calling Types.POJO(Class, Map)
Set<String> declared = Arrays.stream(MyClass.class.getDeclaredFields())
.map(Field::getName)
.collect(Collectors.toSet());
Map<String, TypeInformation<?>> fields = new HashMap<>();
fields.put("username", Types.STRING);
for (String key : fields.keySet()) {
if (!declared.contains(key)) {
throw new IllegalArgumentException("Unknown field: " + key);
}
}
TypeInformation<MyClass> ti = Types.POJO(MyClass.class, fields); Try / catch
try {
TypeInformation<MyType> ti = Types.POJO(MyType.class, fields);
} catch (InvalidTypesException e) {
// re-check field names against getDeclaredFields and report the mismatch
Set<String> valid = Arrays.stream(MyType.class.getDeclaredFields())
.map(Field::getName).collect(Collectors.toSet());
throw new RuntimeException("Invalid fields. Valid names: " + valid, e);
} Prevention
- Cross-check every key in the fields map against the actual declared field names (reflection) in a test.
- After renaming a POJO field, grep for Types.POJO usages and update field maps.
- Prefer Types.POJO(Class) auto-extraction when fields are simple enough, to avoid manual-name drift.
When it happens
Trigger: Calling Types.POJO(MyClass.class, fieldMap) where a key in fieldMap is misspelled, uses the wrong casing, refers to a field that was renamed, or refers to a property name that has a private backing field but the name does not match the actual declared field name. Also triggered when passing a getter-name (e.g. "getName") instead of the field name ("name").
Common situations: Refactoring a POJO and renaming a field without updating the Types.POJO call. Copy-pasting field names with a typo. Using a Lombok @JsonProperty annotation name as the field key instead of the Java field name. Assuming Flink resolves by property name when the field is actually private (getDeclaredField looks for the raw field, not bean properties).
Related errors
- POJO type expected but was: {}
- Cannot instantiate class.
- Invalid POJO field reference "{}".
- Unable to find field "{}" in type {}.
- Nested field expression "{}" not possible on atomic type {}.
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/08366bfd64abd55e.
Report an issue: GitHub.