{"record":{"id":"178f1abe70fe4267","repo":"oracle/graal","slug":"node-field-must-be-annotated-with-input-getsimp","errorCode":null,"errorMessage":"Node field must be annotated with @${Input.getSimpleName()}, @${OptionalInput.getSimpleName()} or @${Successor.getSimpleName()}","messagePattern":"Node field must be annotated with @(.+?), @(.+?) or @(.+?)","errorType":"validation","errorClass":"ElementException","httpStatus":null,"severity":"error","filePath":"compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/nodeinfo/processor/GraphNodeVerifier.java","lineNumber":166,"sourceCode":"                        }\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            }\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) {","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/nodeinfo/processor/GraphNodeVerifier.java#L148-L184","documentation":"Any non-static field whose type is assignable to Node must be annotated with @Input, @OptionalInput or @Successor (the only exception is a field literally named 'Null', used for the null constant). Unannotated Node fields would be invisible to the graph: they would neither be tracked as usages nor serialized/visited, silently corrupting the graph. The processor scans the class and all superclasses when the node class is registered via @NodeInfo.","triggerScenarios":"A field where isAssignableWithErasure(field, Node) is true, none of the three annotations is present, and field.getSimpleName() is not exactly 'Null' (GraphNodeVerifier.java:165-167). Example: 'protected ValueNode cached;' with no annotation in a @NodeInfo class.","commonSituations":"Adding a scratch/cache Node reference to a node class; forgetting the annotation on a newly added edge; subclassing an existing node and adding a Node-typed field; renaming a field to something other than 'Null' that previously relied on the exemption.","solutions":["Decide the edge kind and add @Input, @OptionalInput (value dependency) or @Successor (control-flow) to the field.","If the field must stay outside the graph, mark it transient (transient fields are skipped by scanFields) or static.","If it is a cache recomputed on demand, consider a transient field plus lazy recompute.","Rebuild to confirm."],"exampleFix":"// before\nprotected ValueNode cached;\n\n// after\n@OptionalInput\nprotected ValueNode cached;\n// or, if not a graph edge:\ntransient protected ValueNode cached;","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Every Node-typed field must be @Input/@OptionalInput/@Successor, transient, or static.","Add the annotation in the same commit that introduces the field so builds never drift into this error.","Use 'Null' as the field name only for the intentional null-constant exemption."],"tags":["java","graalvm","annotation-processing","graal-node","graph-invariants","compile-time"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}