{"record":{"id":"a672ac8daf710957","repo":"oracle/graal","slug":"successor-field-must-not-be-public","errorCode":null,"errorMessage":"Successor field must not be public","messagePattern":"Successor 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":160,"sourceCode":"                        }\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)) {\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            }","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/nodeinfo/processor/GraphNodeVerifier.java#L142-L178","documentation":"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.","triggerScenarios":"modifiers.contains(PUBLIC) on a @Successor field in the non-NodeSuccessorList branch (GraphNodeVerifier.java:159-161). Example: '@Successor public AbstractBeginNode trueSuccessor;'.","commonSituations":"Branch nodes (IfNode-style) written with public successor fields; scaffolding copied from tutorials; widening visibility temporarily for a test and forgetting to revert.","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."],"exampleFix":"// before\n@Successor\npublic AbstractBeginNode trueSuccessor;\n\n// after\n@Successor\nprotected AbstractBeginNode trueSuccessor;","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep successor fields protected/package-private so CFG rewiring stays encapsulated.","When porting node code, audit every field's modifiers against the processor rules."],"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-15T22:17:37.221Z"}