{"record":{"id":"c5db7b55c8bd3e5e","repo":"stanfordnlp/CoreNLP","slug":"empty-node-shouldn-t-have-left-branch","errorCode":null,"errorMessage":"Empty node shouldn't have left branch","messagePattern":"Empty node shouldn't have left branch","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/edu/stanford/nlp/util/IntervalTree.java","lineNumber":362,"sourceCode":"\n  private void adjust(TreeNode<E,T> node) {\n    adjustUpwards(node, node.parent);\n  }\n\n  public void check() {\n    check(root);\n  }\n\n  public void check(TreeNode<E,T> treeNode) {\n    Stack<TreeNode<E,T>> todo = new Stack<>();\n    todo.add(treeNode);\n    while (!todo.isEmpty()) {\n      TreeNode<E,T> node = todo.pop();\n      if (node == node.parent) {\n        throw new IllegalStateException(\"node is same as parent!!!\");\n      }\n      if (node.isEmpty()) {\n        if (node.left != null) throw new IllegalStateException(\"Empty node shouldn't have left branch\");\n        if (node.right != null) throw new IllegalStateException(\"Empty node shouldn't have right branch\");\n        continue;\n      }\n      int leftSize = (node.left != null)? node.left.size:0;\n      int rightSize = (node.right != null)? node.right.size:0;\n      E leftMax = (node.left != null)? node.left.maxEnd:null;\n      E rightMax = (node.right != null)? node.right.maxEnd:null;\n      E maxEnd = node.value.getInterval().getEnd();\n      if (leftMax != null && leftMax.compareTo(maxEnd) > 0) {\n        maxEnd = leftMax;\n      }\n      if (rightMax != null && rightMax.compareTo(maxEnd) > 0) {\n        maxEnd = rightMax;\n      }\n      if (!maxEnd.equals(node.maxEnd)) {\n        throw new IllegalStateException(\"max end is not as expected!!!\");\n      }\n      if (node.size != leftSize + rightSize + 1) {","sourceCodeStart":344,"sourceCodeEnd":380,"githubUrl":"https://github.com/stanfordnlp/CoreNLP/blob/1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a/src/edu/stanford/nlp/util/IntervalTree.java#L344-L380","documentation":"check() treats nodes with a null value ('empty' sentinel nodes) as pure placeholders: such a node must have no children. This IllegalStateException fires when an empty node still has a non-null left child, meaning a deletion or rotation left a half-detached node in the structure. It indicates internal corruption of the interval tree, not bad user data.","triggerScenarios":"check() (or balance()/rotateUp() which call it) encounters TreeNode.isEmpty() == true whose left field is non-null — typically after remove() left dangling children on an emptied node.","commonSituations":"Hit during remove-heavy workloads (deleting many intervals then validating); seen when a custom subclass or reflection-based code touched node fields; appeared after an interrupted/concurrent mutation of a shared tree.","solutions":["Rebuild the IntervalTree from scratch (new tree + re-insert all live intervals) to clear the malformed empty node.","Do not keep references to removed nodes or call check()/rotate on stale node objects from a previous tree state.","Serialize access to the tree (single thread or locking); it has no internal synchronization.","If reproducible via public insert/remove only, file a CoreNLP bug with the minimal operation sequence."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Validate the tree after mutation-heavy phases\nassertTreeValid(tree);\nvoid assertTreeValid(IntervalTree<Interval<E>,T> t) {\n  try { t.check(t.root); }\n  catch (IllegalStateException e) { throw new RuntimeException(\"tree corrupt: \" + e.getMessage()); }\n}","typeGuard":null,"tryCatchPattern":"try {\n  tree.remove(interval, value);\n} catch (IllegalStateException e) {\n  tree = rebuildTree(liveIntervals);\n}","preventionTips":["Avoid remove-heavy sequences without re-validating; rebuild periodically if many removals occur.","Discard references to removed nodes immediately.","Do not share the tree across threads without synchronization.","Treat any IllegalStateException from check() as 'rebuild required', not retryable."],"tags":["interval-tree","invariant","empty-node","corenlp"],"backgroundTag":"internal-invariant-violation","analyzedSha":"1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a","analyzedAt":"2026-09-10T02:24:07.274Z","contentChangedAt":"2026-09-10T02:24:07.274Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}