apache/beam · error · RuntimeException
Malformed class : state declaration field is not accessible.
Error message
Malformed %s class %s: state declaration field %s is not accessible.
What it means
Beam reads a DoFn's @StateId-decorated field reflectively to get its StateSpec. If Field.get(target) throws IllegalAccessException (the field is not public or otherwise inaccessible), Beam wraps it in a RuntimeException stating the DoFn class is malformed. This indicates a state declaration field that violates Beam's accessibility requirement.
Solutions
- Make the @StateId-annotated field public (Beam requires state declaration fields to be public)
- Ensure the field is an instance field on the DoFn class itself, not inherited from an inaccessible superclass
- Confirm the field type is StateSpec<...> with a @StateId annotation
- If using a superclass DoFn, expose the field publicly there or restructure so the subclass declares it
Example fix
// before
@StateId("seen")
private final StateSpec<ValueState<Integer>> seenSpec = StateSpecs.value();
// after
@StateId("seen")
public final StateSpec<ValueState<Integer>> seenSpec = StateSpecs.value(); Defensive patterns
Strategy: validation
Validate before calling
// Verify @StateId fields are public before building the pipeline
for (Field f : MyFn.class.getDeclaredFields()) {
if (f.isAnnotationPresent(StateId.class) && !Modifier.isPublic(f.getModifiers())) {
throw new IllegalStateException("@StateId field must be public: " + f.getName());
}
} Type guard
static boolean isAccessibleStateField(Field f) {
return Modifier.isPublic(f.getModifiers())
&& StateSpec.class.isAssignableFrom(f.getType()); Try / catch
try {
pipeline.run();
} catch (RuntimeException e) {
if (e.getMessage().contains("state declaration field")) {
// make the field public and retry
}
} Prevention
- Declare @StateId/@TimerId/@TimerFamily fields always public
- Add a unit test that reflectively checks DoFn declaration field visibility
- Avoid storing spec fields in private base classes
When it happens
Trigger: Using @StateId on a field that is private/protected/package-private (or in a non-public class with restricted access), so reflection via stateDeclaration.field().get(target) fails with IllegalAccessException while retrieving the StateSpec.
Common situations: Developers habitually declare fields private; refactoring moves a DoFn into another class/package and field access rules tighten; annotation-processor-less environments where a private @StateId field was never validated at compile time.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Malformed class : timer declaration field is not accessible.
- AutoValue builder class
- Can not call prepareRun
- Cannot create from non-Java
- cannot register Coder : does not have an accessible method…
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/700a6f89b79ca642.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/reflect/DoFnSignatures.java:2534
}
}
}
public static StateSpec<?> getStateSpecOrThrow(
StateDeclaration stateDeclaration, DoFn<?, ?> target) {
try {
Object fieldValue = stateDeclaration.field().get(target);
checkState(
fieldValue instanceof StateSpec,
"Malformed %s class %s: state declaration field %s does not have type %s.",
format(DoFn.class),
target.getClass().getName(),
stateDeclaration.field().getName(),
StateSpec.class);
return (StateSpec<?>) stateDeclaration.field().get(target);
} catch (IllegalAccessException exc) {
throw new RuntimeException(
String.format(
"Malformed %s class %s: state declaration field %s is not accessible.",
format(DoFn.class), target.getClass().getName(), stateDeclaration.field().getName()));
}
}
public static TimerSpec getTimerSpecOrThrow(
TimerDeclaration timerDeclaration, DoFn<?, ?> target) {
try {
Object fieldValue = timerDeclaration.field().get(target);
checkState(
fieldValue instanceof TimerSpec,
"Malformed %s class %s: timer declaration field %s does not have type %s.",
format(DoFn.class),
target.getClass().getName(),
timerDeclaration.field().getName(),
TimerSpec.class);
View on GitHub (pinned to 12126d8942)