oracle/graal · error · IOException

No class for

Error message

No class for 

What it means

Before serializing a node, GraphProtocol resolves its NodeClass via findClassForNode; a null result means the protocol cannot describe this node type to the reader, and it throws IOException('No class for <node>') rather than emitting an unparseable stream. The lookup fails for node classes that are not registered/visible to the dump's class mapping — typically foreign or dynamically created node types.

Source

Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graphio/GraphProtocol.java:594

                    writeShort((char) 0);
                } else {
                    int listSize = list.size();
                    if (listSize != ((char) listSize)) {
                        throw new IOException("Too many nodes in list: " + list.size());
                    }
                    writeShort((char) listSize);
                    for (Node edge : list) {
                        writeNodeRef(edge);
                    }
                }
            }
        }
    }

    private NodeClass classForNode(Node node) throws IOException {
        NodeClass clazz = findClassForNode(node);
        if (clazz == null) {
            throw new IOException("No class for " + node);
        }
        return clazz;
    }

    private void writeNodeRef(Node node) throws IOException {
        writeInt(findNodeId(node));
    }

    private void writeBlocks(Collection<? extends Block> blocks, Graph info) throws IOException {
        if (blocks != null) {
            for (Block block : blocks) {
                Collection<? extends Node> nodes = findBlockNodes(info, block);
                if (nodes == null) {
                    writeInt(0);
                    return;
                }
            }
            writeInt(blocks.size());

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Ensure every node class in the dumped graph has working NodeClass metadata (static TYPE initialized; see NodeClass.get).
  2. If you override GraphProtocol.findClassForNode, add a branch covering the failing node type (log node.getClass() to identify it).
  3. Initialize the node's class (Class.forName with initialize=true) before dumping so TYPE is populated.
  4. Filter the failing nodes out of the dump (custom node filtering) if they need not be visualized.

Example fix

// before
class MyProtocol extends GraphProtocol {
    protected NodeClass findClassForNode(Node node) {
        return registry.lookup(node.getClass()); // returns null for foreign nodes -> IOException
    }
}

// after
class MyProtocol extends GraphProtocol {
    protected NodeClass findClassForNode(Node node) {
        NodeClass nc = registry.lookup(node.getClass());
        return nc != null ? nc : NodeClass.get(node.getClass()); // fall back to TYPE metadata
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure every node type in the graph has resolvable NodeClass metadata before dumping
for (Node n : graph.getNodes()) {
    if (NodeClass.get(n.getClass()) == null) {
        throw new IllegalStateException("Undumpable node type: " + n.getClass());
    }
}

Type guard

static boolean isDumpableNodeType(Class<? extends Node> c) {
    try {
        return NodeClass.get(c) != null;
    } catch (RuntimeException e) {
        return false;
    }
}

Try / catch

try {
    output.print(graph, ...);
} catch (IOException e) {
    if (e.getMessage().startsWith("No class for")) {
        // identify the node type from the message, initialize its class / extend findClassForNode, re-dump
        log.warning("Skipping dump: " + e.getMessage());
    } else throw e;
}

Prevention

When it happens

Trigger: Dumping a graph containing node instances whose class has no NodeClass resolvable by the configured protocol (missing/failed static TYPE initialization, node classes from a classloader the protocol cannot introspect, or proxies/anonymous node subclasses). Custom GraphProtocol subclasses whose findClassForNode does not cover all node types present.

Common situations: Dumping graphs from plugins/libraries that define their own node types without proper @NodeInfo/NodeClass metadata. Running under classloader setups (e.g. some test harnesses or polyglot runtimes) where reflection on node classes fails silently. Overriding findClassForNode and forgetting a category of nodes.

Related errors


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