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
- 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.
- Keep separate types for nodes and node classes in your graph model so the two lookups cannot collide.
- 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
- Use distinct types for nodes and node classes in custom graph models.
- Assert the classForNode contract in a dump smoke test.
- Review all GraphStructure overrides as a set; contracts are interdependent.
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
- Should be recognized as signature:
- edgeType method shall return an enum! Was:
- nodeClassType method shall return a Java class (instance of
- File header is missing
- Bad pattern: {}
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/3dcef8bf7cf989fd.
Report an issue: GitHub.