oracle/graal · error · IllegalStateException

classForNode method shall return node class representation r

Error message

classForNode method shall return node class representation rather than node: 

What it means

ProtocolImpl.findClassForNode validates the result of GraphStructure.classForNode: the method must return the class-of-a-node representation (NodeClass), not a node instance itself. The check fails when the returned NodeClass is not recognizable via findNodeClass, or when it is recognizable as a node (findNode(clazz) != null), i.e. the customization returned a node object where a node-class object was required. The IllegalStateException aborts dumping because the writer would then emit a node in a node-class pool slot and corrupt the stream.

Source

Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graphio/ProtocolImpl.java:85

    protected Graph findGraph(Graph current, Object obj) {
        return structure.graph(current, obj);
    }

    @Override
    protected Node findNode(Object obj) {
        return structure.node(obj);
    }

    @Override
    protected NodeClass findNodeClass(Object obj) {
        return structure.nodeClass(obj);
    }

    @Override
    protected NodeClass findClassForNode(Node obj) {
        NodeClass clazz = structure.classForNode(obj);
        if (clazz != null && (findNodeClass(clazz) == null || findNode(clazz) != null)) {
            throw new IllegalStateException("classForNode method shall return node class representation rather than node: " + clazz);
        }
        return clazz;
    }

    @Override
    protected String findNameTemplate(NodeClass clazz) {
        return structure.nameTemplate(clazz);
    }

    @Override
    protected int findNodeId(Node n) {
        return structure.nodeId(n);
    }

    @Override
    protected boolean hasPredecessor(Node node) {
        return structure.nodeHasPredecessor(node);
    }

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Return the node's class/prototype object from classForNode, never a node instance: ensure findNodeClass(structure.classForNode(n)) != null and findNode(structure.classForNode(n)) == null.
  2. Keep separate types for nodes and node classes in your graph model so the two lookups cannot collide.
  3. Write a validation unit test that calls classForNode on sample nodes and asserts both conditions above.

Example fix

// before
@Override
public NodeClass classForNode(Node obj) {
    return obj; // a node, not a node class -> IllegalStateException
}

// after
@Override
public NodeClass classForNode(Node obj) {
    return obj.nodeClass(); // genuine node-class representation
}
Defensive patterns

Strategy: validation

Validate before calling

NodeClass clazz = structure.classForNode(node);
if (clazz == null || structure.nodeClass(clazz) == null || structure.node(clazz) != null) {
    throw new IllegalStateException("classForNode must return a node class, not a node: " + clazz);
}

Prevention

When it happens

Trigger: Implementing GraphStructure.classForNode to return the node itself (or a lookup key that is actually a node) instead of its NodeClass; inconsistent overrides of classForNode vs nodeClass/node in a custom GraphStructure.

Common situations: Adapting graphio to a non-Graal graph model (domain graphs, LLVM-style graphs) where the distinction between 'node' and 'node class' objects is easy to blur; refactoring a custom structure and forgetting that classForNode has a different return contract than node.

Related errors


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