oracle/graal · error · ElementException
Successor list field must not be public
Error message
Successor list field must not be public
What it means
NodeSuccessorList fields annotated @Successor must not be public. Successor wiring must go through node methods so CFG consistency is preserved; exposing the list publicly would let arbitrary code splice the control-flow graph incorrectly. The verifier throws this ElementException during compilation of any @NodeInfo-annotated class.
Source
Thrown at compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/nodeinfo/processor/GraphNodeVerifier.java:150
}
} else {
if (!isAssignableWithErasure(field, Node) && field.getKind() == ElementKind.INTERFACE) {
throw new ElementException(field, "Input field type must be an interface or assignable to Node");
}
if (modifiers.contains(FINAL)) {
throw new ElementException(field, "Input field must not be final");
}
if (modifiers.contains(PUBLIC)) {
throw new ElementException(field, "Input field must not be public");
}
}
} else if (isSuccessor) {
if (isAssignableWithErasure(field, NodeSuccessorList)) {
if (modifiers.contains(FINAL)) {
throw new ElementException(field, "Successor list field must not be final");
}
if (modifiers.contains(PUBLIC)) {
throw new ElementException(field, "Successor list field must not be public");
}
} else {
if (!isAssignableWithErasure(field, Node)) {
throw new ElementException(field, "Successor field must be a Node type");
}
if (modifiers.contains(FINAL)) {
throw new ElementException(field, "Successor field must not be final");
}
if (modifiers.contains(PUBLIC)) {
throw new ElementException(field, "Successor field must not be public");
}
}
} else {
if (isAssignableWithErasure(field, Node) && !field.getSimpleName().contentEquals("Null")) {
throw new ElementException(field, "Node field must be annotated with @" + Input.getSimpleName() + ", @" + OptionalInput.getSimpleName() + " or @" + Successor.getSimpleName());
}
if (isAssignableWithErasure(field, NodeInputList)) {View on GitHub (pinned to a66e9ccd1d)
Solutions
- Change the field to protected or package-private.
- If tests need access, add accessor methods rather than widening visibility.
- Rebuild with mx build to confirm the processor passes.
Example fix
// before @Successor public NodeSuccessorList<FixedNode> successors; // after @Successor protected NodeSuccessorList<FixedNode> successors;
Defensive patterns
Strategy: validation
Prevention
- Successor wiring must stay behind node APIs: keep successor fields non-public.
- Do not expose successor lists for test assertions; add package-private observers instead.
When it happens
Trigger: modifiers.contains(PUBLIC) on a @Successor field assignable to NodeSuccessorList (GraphNodeVerifier.java:149-151). Example: '@Successor public NodeSuccessorList<AbstractBeginNode> successors;'.
Common situations: Control-flow nodes copied from public-API sample code; generated node scaffolds with public fields; refactoring while making fields 'more visible' for tests.
Related errors
- Successor field must not be public
- Input list field must not be public
- Input field must not be public
- Successor list field must not be final
- Successor field must be a Node type
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/665b83f6251a4c97.
Report an issue: GitHub.