oracle/graal · error · ElementException

Field cannot be both input and successor

Error message

Field cannot be both input and successor

What it means

Thrown by GraphNodeVerifier (part of the Graal node-info annotation processor) when a field in a Node class carries both @Input (or @OptionalInput) and @Successor annotations. Inputs and successors are distinct edge kinds in Graal's graph model with different invariants (inputs have usages, successors form the control-flow topology), so a single field cannot be both. It surfaces as a compile-time ElementException on the offending field.

Source

Thrown at compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/nodeinfo/processor/GraphNodeVerifier.java:123

    private void scanFields(TypeElement node) {
        TypeElement currentClazz = node;
        do {
            for (VariableElement field : ElementFilter.fieldsIn(currentClazz.getEnclosedElements())) {
                Set<Modifier> modifiers = field.getModifiers();
                if (modifiers.contains(STATIC) || modifiers.contains(TRANSIENT)) {
                    continue;
                }

                List<? extends AnnotationMirror> annotations = field.getAnnotationMirrors();

                boolean isNonOptionalInput = findAnnotationMirror(annotations, Input) != null;
                boolean isOptionalInput = findAnnotationMirror(annotations, OptionalInput) != null;
                boolean isSuccessor = findAnnotationMirror(annotations, Successor) != null;

                if (isNonOptionalInput || isOptionalInput) {
                    if (findAnnotationMirror(annotations, Successor) != null) {
                        throw new ElementException(field, "Field cannot be both input and successor");
                    } else if (isNonOptionalInput && isOptionalInput) {
                        throw new ElementException(field, "Inputs must be either optional or non-optional");
                    } else if (isAssignableWithErasure(field, NodeInputList)) {
                        if (modifiers.contains(FINAL)) {
                            throw new ElementException(field, "Input list field must not be final");
                        }
                        if (modifiers.contains(PUBLIC)) {
                            throw new ElementException(field, "Input list field must not be public");
                        }
                    } else {
                        if (!isAssignableWithErasure(field, Node) && field.getKind() == ElementKind.INTERFACE) {
                            throw new ElementException(field, "Input field type must be an interface or assignable to Node");
                        }
                        if (modifiers.contains(FINAL)) {
                            throw new ElementException(field, "Input field must not be final");
                        }
                        if (modifiers.contains(PUBLIC)) {
                            throw new ElementException(field, "Input field must not be public");

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Decide the edge's role: data/usage edge -> keep @Input/@OptionalInput; control-flow edge -> keep @Successor; remove the other annotation.
  2. If you truly need both relationships, model them as two separate fields.
  3. Re-run the build; the processor re-verifies on the next annotation-processing round.

Example fix

// before
@Input
@Successor
Node next;

// after (control-flow edge -> @Successor only)
@Successor
Node next;
Defensive patterns

Strategy: validation

Try / catch

This is a compile-time ElementException from the node-info processor; there is no runtime catch. CI must fail the build on it.

Prevention

When it happens

Trigger: Declaring a Node field annotated with e.g. @Input @Successor NodeClass field; or @OptionalInput @Successor. The verifier checks annotation mirrors directly on non-static, non-transient fields of classes it processes.

Common situations: Copy-paste when adding a successor field from an input field template; refactorings that change an edge's role without removing the old annotation; experimental node classes where the author was unsure which edge kind to use.

Related errors


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/f64c93d00451e4f1. Report an issue: GitHub.