{"record":{"id":"d4c79c359ff4a9b4","repo":"oracle/graal","slug":"nodesuccessorlist-field-must-be-annotated-with","errorCode":null,"errorMessage":"NodeSuccessorList field must be annotated with @${Successor.getSimpleName()}","messagePattern":"NodeSuccessorList field must be annotated with @(.+?)","errorType":"validation","errorClass":"ElementException","httpStatus":null,"severity":"error","filePath":"compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/nodeinfo/processor/GraphNodeVerifier.java","lineNumber":172,"sourceCode":"                            throw new ElementException(field, \"Successor field must be a Node type\");\n                        }\n                        if (modifiers.contains(FINAL)) {\n                            throw new ElementException(field, \"Successor field must not be final\");\n                        }\n                        if (modifiers.contains(PUBLIC)) {\n                            throw new ElementException(field, \"Successor field must not be public\");\n                        }\n                    }\n\n                } else {\n                    if (isAssignableWithErasure(field, Node) && !field.getSimpleName().contentEquals(\"Null\")) {\n                        throw new ElementException(field, \"Node field must be annotated with @\" + Input.getSimpleName() + \", @\" + OptionalInput.getSimpleName() + \" or @\" + Successor.getSimpleName());\n                    }\n                    if (isAssignableWithErasure(field, NodeInputList)) {\n                        throw new ElementException(field, \"NodeInputList field must be annotated with @\" + Input.getSimpleName() + \" or @\" + OptionalInput.getSimpleName());\n                    }\n                    if (isAssignableWithErasure(field, NodeSuccessorList)) {\n                        throw new ElementException(field, \"NodeSuccessorList field must be annotated with @\" + Successor.getSimpleName());\n                    }\n                    if (modifiers.contains(PUBLIC) && !modifiers.contains(FINAL)) {\n                        throw new ElementException(field, \"Data field must be final if public\");\n                    }\n                }\n            }\n            currentClazz = getSuperType(currentClazz);\n        } while (!isObject(getSuperType(currentClazz).asType()));\n    }\n\n    private AnnotationMirror findAnnotationMirror(List<? extends AnnotationMirror> mirrors, TypeElement expectedAnnotationType) {\n        for (AnnotationMirror mirror : mirrors) {\n            if (sameType(mirror.getAnnotationType(), expectedAnnotationType.asType())) {\n                return mirror;\n            }\n        }\n        return null;\n    }","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/nodeinfo/processor/GraphNodeVerifier.java#L154-L190","documentation":"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.","triggerScenarios":"isAssignableWithErasure(field, NodeSuccessorList) is true and @Successor is absent (GraphNodeVerifier.java:171-173). Example: 'protected NodeSuccessorList<FixedNode> branches;' without annotation.","commonSituations":"Adding a multi-target successor list (switch/loop nodes) and forgetting @Successor; annotating it with @Input by mistake; porting control-flow nodes between suites.","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."],"exampleFix":"// before\nprotected NodeSuccessorList<FixedNode> blockSuccessors;\n\n// after\n@Successor\nprotected NodeSuccessorList<FixedNode> blockSuccessors;","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["NodeSuccessorList fields always need @Successor.","Do not annotate successor lists with @Input — the processor also rejects mixed annotations."],"tags":["java","graalvm","annotation-processing","graal-node","control-flow","graph-invariants","compile-time"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}