{"record":{"id":"dc95210d8f7e834c","repo":"oracle/graal","slug":"successor-field-must-not-be-final","errorCode":null,"errorMessage":"Successor field must not be final","messagePattern":"Successor field must not be final","errorType":"validation","errorClass":"ElementException","httpStatus":null,"severity":"error","filePath":"compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/nodeinfo/processor/GraphNodeVerifier.java","lineNumber":157,"sourceCode":"                        }\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)) {\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\");","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/nodeinfo/processor/GraphNodeVerifier.java#L139-L175","documentation":"Single-valued @Successor fields (type assignable to Node, not a list) must not be final. The runtime rewrites successor references during CFG transformations (e.g. replacing a fixed node, deleting branches), which requires the field to be assignable. The NodeInfo annotation processor rejects final successor fields at compile time.","triggerScenarios":"modifiers.contains(FINAL) on a @Successor field in the non-NodeSuccessorList branch (GraphNodeVerifier.java:156-158). Example: '@Successor protected final FixedWithNextNode next;'.","commonSituations":"Writing fixed nodes with an immutable 'next' pointer; IDE final refactors applied broadly; converting a builder-style class into a node.","solutions":["Remove final from the successor field.","Assign it in the constructor and let graph transformations mutate it via setNext-style methods.","Keep visibility protected or package-private.","Rebuild to confirm."],"exampleFix":"// before\n@Successor\nprotected final FixedWithNextNode next;\n\n// after\n@Successor\nprotected FixedWithNextNode next;","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Successor fields are rewritten during CFG transformations; never make them final.","Provide setNext-style mutators rather than relying on constructor-only assignment."],"tags":["java","graalvm","annotation-processing","graal-node","control-flow","compile-time"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}