{"record":{"id":"665b83f6251a4c97","repo":"oracle/graal","slug":"successor-list-field-must-not-be-public","errorCode":null,"errorMessage":"Successor list field must not be public","messagePattern":"Successor list field must not be public","errorType":"validation","errorClass":"ElementException","httpStatus":null,"severity":"error","filePath":"compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/nodeinfo/processor/GraphNodeVerifier.java","lineNumber":150,"sourceCode":"                        }\n                    } else {\n                        if (!isAssignableWithErasure(field, Node) && field.getKind() == ElementKind.INTERFACE) {\n                            throw new ElementException(field, \"Input field type must be an interface or assignable to Node\");\n                        }\n                        if (modifiers.contains(FINAL)) {\n                            throw new ElementException(field, \"Input field must not be final\");\n                        }\n                        if (modifiers.contains(PUBLIC)) {\n                            throw new ElementException(field, \"Input field must not be public\");\n                        }\n                    }\n                } else if (isSuccessor) {\n                    if (isAssignableWithErasure(field, NodeSuccessorList)) {\n                        if (modifiers.contains(FINAL)) {\n                            throw new ElementException(field, \"Successor list field must not be final\");\n                        }\n                        if (modifiers.contains(PUBLIC)) {\n                            throw new ElementException(field, \"Successor list field must not be public\");\n                        }\n                    } else {\n                        if (!isAssignableWithErasure(field, Node)) {\n                            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)) {","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/nodeinfo/processor/GraphNodeVerifier.java#L132-L168","documentation":"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.","triggerScenarios":"modifiers.contains(PUBLIC) on a @Successor field assignable to NodeSuccessorList (GraphNodeVerifier.java:149-151). Example: '@Successor public NodeSuccessorList<AbstractBeginNode> successors;'.","commonSituations":"Control-flow nodes copied from public-API sample code; generated node scaffolds with public fields; refactoring while making fields 'more visible' for tests.","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."],"exampleFix":"// before\n@Successor\npublic NodeSuccessorList<FixedNode> successors;\n\n// after\n@Successor\nprotected NodeSuccessorList<FixedNode> successors;","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["java","graalvm","annotation-processing","graal-node","control-flow","encapsulation","compile-time"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}