{"record":{"id":"3dcef8bf7cf989fd","repo":"oracle/graal","slug":"classfornode-method-shall-return-node-class-repres","errorCode":null,"errorMessage":"classForNode method shall return node class representation rather than node: ","messagePattern":"classForNode method shall return node class representation rather than node: ","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graphio/ProtocolImpl.java","lineNumber":85,"sourceCode":"    protected Graph findGraph(Graph current, Object obj) {\n        return structure.graph(current, obj);\n    }\n\n    @Override\n    protected Node findNode(Object obj) {\n        return structure.node(obj);\n    }\n\n    @Override\n    protected NodeClass findNodeClass(Object obj) {\n        return structure.nodeClass(obj);\n    }\n\n    @Override\n    protected NodeClass findClassForNode(Node obj) {\n        NodeClass clazz = structure.classForNode(obj);\n        if (clazz != null && (findNodeClass(clazz) == null || findNode(clazz) != null)) {\n            throw new IllegalStateException(\"classForNode method shall return node class representation rather than node: \" + clazz);\n        }\n        return clazz;\n    }\n\n    @Override\n    protected String findNameTemplate(NodeClass clazz) {\n        return structure.nameTemplate(clazz);\n    }\n\n    @Override\n    protected int findNodeId(Node n) {\n        return structure.nodeId(n);\n    }\n\n    @Override\n    protected boolean hasPredecessor(Node node) {\n        return structure.nodeHasPredecessor(node);\n    }","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graphio/ProtocolImpl.java#L67-L103","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n@Override\npublic NodeClass classForNode(Node obj) {\n    return obj; // a node, not a node class -> IllegalStateException\n}\n\n// after\n@Override\npublic NodeClass classForNode(Node obj) {\n    return obj.nodeClass(); // genuine node-class representation\n}","handlingStrategy":"validation","validationCode":"NodeClass clazz = structure.classForNode(node);\nif (clazz == null || structure.nodeClass(clazz) == null || structure.node(clazz) != null) {\n    throw new IllegalStateException(\"classForNode must return a node class, not a node: \" + clazz);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["graphio","api-contract","custom-structure","validation"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}