openjdk/jdk · critical
error: node is null
Error message
error: node is null
What it means
ArchDesc::buildMList internal check: a null MatchRule node reached the list builder ('error: node is null'). buildMList is invoked with node == nullptr from a caller that should always pass a child rule; note the code already dereferences node->_opType above for the index lookup, so in practice the preceding lookup crash/error usually fires first — this message marks a structural inconsistency in the match-rule tree built by the parser.
Source
Thrown at src/hotspot/share/adlc/archDesc.cpp:559
leftstr = rightstr = nullptr;
// Do not process leaves of the Match Tree if they are not ideal
if ((node) && (node->_lChild == nullptr) && (node->_rChild == nullptr) &&
((form = (Form *)_globalNames[node->_opType]) != nullptr) &&
(!form->ideal_only())) {
return;
}
// Identify index position among ideal operands
intptr_t index = _last_opcode;
const char *indexStr = node ? node->_opType : (char *) " ";
index = (intptr_t)_idealIndex[indexStr];
if (index == 0) {
fprintf(stderr, "error: operand \"%s\" not found\n", indexStr);
assert(0, "fatal error");
}
if (node == nullptr) {
fprintf(stderr, "error: node is null\n");
assert(0, "fatal error");
}
// Build MatchLists for children
// Check each child for an internal operand name, and use that name
// for the parent's matchlist entry if it exists
mnode = node->_lChild;
if (mnode) {
buildMList(mnode, nullptr, nullptr, nullptr, nullptr);
leftstr = mnode->_internalop ? mnode->_internalop : mnode->_opType;
}
mnode = node->_rChild;
if (mnode) {
buildMList(mnode, nullptr, nullptr, nullptr, nullptr);
rightstr = mnode->_internalop ? mnode->_internalop : mnode->_opType;
}
// Grab the string for the opcode of this list entry
if (rootOp == nullptr) {
opcode = (node->_internalop) ? node->_internalop : node->_opType;View on GitHub (pinned to 88dfb74bbe)
Solutions
- Fix the syntax/operand errors reported earlier in the log first; this message is usually secondary
- Check the flagged instruction's match rule has a well-formed '( result operand )' tree with both children present
- Restore the rule from a known-good revision and reapply the edit
Defensive patterns
Strategy: validation
Validate before calling
make adlc 2>&1 | grep -cE 'syntax error|operand .* not found' # nonzero => fix primary errors; 'node is null' is secondary
Prevention
- Always fix syntax/operand errors first; null-node is fallout
- Give every match rule a complete '( result child... )' tree
- Recover .ad files from version control after bad merges
When it happens
Trigger: A malformed or truncated match rule (parser produced a rule with missing children), or ADLC caller logic passing null where a child rule was expected (buildMList(mnode, ...) recursion with an absent child).
Common situations: Editing match-rule nesting by hand and dropping a child operand; .ad merge conflicts leaving a half-formed rule; almost always accompanied by [94] or a syntax error that is the true cause.
Related errors
- Ideal node missing: %s
- Invalid match rule %s <-- ( %s )
- error: operand \"%s\" not found
- Error: Out of memory in ADLC\n
- %s: Found %d syntax error
AI-assisted analysis of openjdk/jdk@88dfb74bbe (2026-08-14).
Data as JSON: /api/errors/968e28a2b7f943f8.
Report an issue: GitHub.