{"record":{"id":"1bcab42dd702d412","repo":"oracle/graal","slug":"inputs-must-be-either-optional-or-non-optional","errorCode":null,"errorMessage":"Inputs must be either optional or non-optional","messagePattern":"Inputs must be either optional or non-optional","errorType":"validation","errorClass":"ElementException","httpStatus":null,"severity":"error","filePath":"compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/nodeinfo/processor/GraphNodeVerifier.java","lineNumber":125,"sourceCode":"        TypeElement currentClazz = node;\n        do {\n            for (VariableElement field : ElementFilter.fieldsIn(currentClazz.getEnclosedElements())) {\n                Set<Modifier> modifiers = field.getModifiers();\n                if (modifiers.contains(STATIC) || modifiers.contains(TRANSIENT)) {\n                    continue;\n                }\n\n                List<? extends AnnotationMirror> annotations = field.getAnnotationMirrors();\n\n                boolean isNonOptionalInput = findAnnotationMirror(annotations, Input) != null;\n                boolean isOptionalInput = findAnnotationMirror(annotations, OptionalInput) != null;\n                boolean isSuccessor = findAnnotationMirror(annotations, Successor) != null;\n\n                if (isNonOptionalInput || isOptionalInput) {\n                    if (findAnnotationMirror(annotations, Successor) != null) {\n                        throw new ElementException(field, \"Field cannot be both input and successor\");\n                    } else if (isNonOptionalInput && isOptionalInput) {\n                        throw new ElementException(field, \"Inputs must be either optional or non-optional\");\n                    } else if (isAssignableWithErasure(field, NodeInputList)) {\n                        if (modifiers.contains(FINAL)) {\n                            throw new ElementException(field, \"Input list field must not be final\");\n                        }\n                        if (modifiers.contains(PUBLIC)) {\n                            throw new ElementException(field, \"Input list field must not be public\");\n                        }\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                    }","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/nodeinfo/processor/GraphNodeVerifier.java#L107-L143","documentation":"Thrown by GraphNodeVerifier when a Node field is annotated with both @Input and @OptionalInput simultaneously. Optionality is a single tri-state (absent, optional, non-optional), not a set of flags; annotating both makes the edge's nullability undefined and the generated node plumbing cannot pick one behavior, so the processor rejects it at compile time.","triggerScenarios":"A field declared as @Input @OptionalInput Node value; the verifier sets isNonOptionalInput and isOptionalInput booleans from annotation mirrors and throws when both are true (before the input/successor check would, since that is checked first only for the Successor conflict).","commonSituations":"Adding @OptionalInput to an existing @Input field during a refactor to permit null, and forgetting to remove @Input; IDE auto-complete inserting both; merging node classes where annotations from two variants accumulate.","solutions":["Keep exactly one annotation: @Input for a required edge, @OptionalInput for one that may be null.","When making an input optional, also audit usages: optional inputs require null checks at use sites and allowedUsage changes.","Remove the redundant annotation and rebuild so the annotation processor re-validates."],"exampleFix":"// before\n@Input\n@OptionalInput\nValueNode value;\n\n// after\n@OptionalInput\nValueNode value;","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":"Compile-time annotation-processing error; no runtime catch exists. Fix the field declaration and rebuild.","preventionTips":["Use @Input for required edges and @OptionalInput for nullable edges — never both.","When relaxing an input to optional, delete @Input in the same edit.","Beware IDE auto-import inserting both annotations during refactors."],"tags":["graalvm","node-api","annotation-processing","compile-time","graph"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}