oracle/graal · error · ElementException
NodeSuccessorList field must be annotated with @${Successor.
Error message
NodeSuccessorList field must be annotated with @${Successor.getSimpleName()} What it means
NodeSuccessorList fields must be annotated with @Successor. A successor list without the annotation would hold control-flow edges the graph cannot see or maintain, so the NodeInfo processor rejects it at compile time. This is the control-flow counterpart of the NodeInputList rule and applies to every non-static, non-transient field in the node hierarchy.
Source
Thrown at compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/nodeinfo/processor/GraphNodeVerifier.java:172
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");
}
}
}
currentClazz = getSuperType(currentClazz);
} while (!isObject(getSuperType(currentClazz).asType()));
}
private AnnotationMirror findAnnotationMirror(List<? extends AnnotationMirror> mirrors, TypeElement expectedAnnotationType) {
for (AnnotationMirror mirror : mirrors) {
if (sameType(mirror.getAnnotationType(), expectedAnnotationType.asType())) {
return mirror;
}
}
return null;
}View on GitHub (pinned to a66e9ccd1d)
Solutions
- Add @Successor to the NodeSuccessorList field.
- If the field is actually a value dependency, change its type to NodeInputList and use @Input/@OptionalInput.
- If it is not a graph edge, use a non-special list type or mark it transient/static.
- Rebuild to confirm.
Example fix
// before protected NodeSuccessorList<FixedNode> blockSuccessors; // after @Successor protected NodeSuccessorList<FixedNode> blockSuccessors;
Defensive patterns
Strategy: validation
Prevention
- NodeSuccessorList fields always need @Successor.
- Do not annotate successor lists with @Input — the processor also rejects mixed annotations.
When it happens
Trigger: isAssignableWithErasure(field, NodeSuccessorList) is true and @Successor is absent (GraphNodeVerifier.java:171-173). Example: 'protected NodeSuccessorList<FixedNode> branches;' without annotation.
Common situations: Adding a multi-target successor list (switch/loop nodes) and forgetting @Successor; annotating it with @Input by mistake; porting control-flow nodes between suites.
Related errors
- Successor list field must not be final
- Successor list field must not be public
- Successor field must be a Node type
- Successor field must not be final
- Successor field must not be public
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/d4c79c359ff4a9b4.
Report an issue: GitHub.