oracle/graal · error · ElementException
Successor field must not be public
Error message
Successor field must not be public
What it means
Single-valued @Successor fields must not be public. Successor edges are part of the control-flow graph and may only be rewired through node APIs that keep the CFG consistent; a public field would bypass those safeguards. GraphNodeVerifier throws this ElementException while scanning the node hierarchy during annotation processing.
Source
Thrown at compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/nodeinfo/processor/GraphNodeVerifier.java:160
}
}
} 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)) {
throw new ElementException(field, "NodeInputList field must be annotated with @" + Input.getSimpleName() + " or @" + OptionalInput.getSimpleName());
}
if (isAssignableWithErasure(field, NodeSuccessorList)) {
throw new ElementException(field, "NodeSuccessorList field must be annotated with @" + Successor.getSimpleName());
}
if (modifiers.contains(PUBLIC) && !modifiers.contains(FINAL)) {
throw new ElementException(field, "Data field must be final if public");
}
}
}View on GitHub (pinned to a66e9ccd1d)
Solutions
- Reduce visibility to protected or package-private.
- Expose controlled mutators (e.g. setTrueSuccessor) instead of the raw field.
- Rebuild with mx build to confirm.
Example fix
// before @Successor public AbstractBeginNode trueSuccessor; // after @Successor protected AbstractBeginNode trueSuccessor;
Defensive patterns
Strategy: validation
Prevention
- Keep successor fields protected/package-private so CFG rewiring stays encapsulated.
- When porting node code, audit every field's modifiers against the processor rules.
When it happens
Trigger: modifiers.contains(PUBLIC) on a @Successor field in the non-NodeSuccessorList branch (GraphNodeVerifier.java:159-161). Example: '@Successor public AbstractBeginNode trueSuccessor;'.
Common situations: Branch nodes (IfNode-style) written with public successor fields; scaffolding copied from tutorials; widening visibility temporarily for a test and forgetting to revert.
Related errors
- Successor list 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/a672ac8daf710957.
Report an issue: GitHub.