stanfordnlp/CoreNLP · error · ParseException

Illegal number of nodes given to createSubtree (

Error message

Illegal number of nodes given to createSubtree (

What it means

ParseException thrown by the generated Tsurgeon parser when the createSubtree operator is given a number of node arguments other than 1 or 2. createSubtree takes a label (root) plus either one node to become the sole child or two nodes (head and dependent); any other arity is rejected. This copy lives in the generated TsurgeonParser.jj (line 303); the hand-written grammar is in TsurgeonParser.jjt:177.

Solutions

  1. Provide exactly one node selection (single child) or two (first = head, second = dependent) after the label.
  2. Check the Tsurgeon script for a missing/extra node list after createSubtree LABEL.
  3. Validate the operation arity programmatically before running Tsurgeon.processPatternsOnTree.

Example fix

// before (three selections)
createSubtree NP node1 node2 node3
// after (head + dependent)
createSubtree NP node1 node2
Defensive patterns

Strategy: validation

Validate before calling

boolean validCreateSubtreeArity(String tsurgeonOp) {
  String[] parts = tsurgeonOp.trim().split("\\s+");
  return parts.length >= 2 && parts[0].equals("createSubtree") && (parts.length == 3 || parts.length == 4);
}

Try / catch

try { Tsurgeon.parseOperation(op); } catch (ParseException e) { throw new IllegalArgumentException("createSubtree needs exactly 1 or 2 node selections: " + op, e); }

Prevention

When it happens

Trigger: Executing a Tsurgeon script whose createSubtree operation's node-selection list has 0 or 3+ selections, e.g. "createSubtree LABEL" with no node selection or with a list of three nodes; the size check at TsurgeonParser.jj:303 throws.

Common situations: Hand-writing tsurgeon operation files with missing or extra node specifications; concatenating operations and leaving a dangling selection; misremembering whether createSubtree takes one or two arguments.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10). Data as JSON: /api/errors/1980234cb62b0454. Report an issue: GitHub.

Appendix: source

Thrown at src/edu/stanford/nlp/trees/tregex/tsurgeon/TsurgeonParser.jj:303

  operator = <INSERT> tree = TreeRoot(false) loc = Location()/*@bgen(jjtree)*/
    {
      jjtree.closeNodeScope(jjtn000, true);
      jjtc000 = false;
    }
/*@egen*/
    { return new InsertNode(tree, loc); }
| operator = <CREATE_SUBTREE> tree = TreeRoot(false) nodeSelections = NodeSelectionList(new ArrayList<TsurgeonPattern>())/*@bgen(jjtree)*/
    {
      jjtree.closeNodeScope(jjtn000, true);
      jjtc000 = false;
    }
/*@egen*/
    { if (nodeSelections.size() == 1) {
        return new CreateSubtreeNode(nodeSelections.get(0), tree);
      } else if (nodeSelections.size() == 2) {
        return new CreateSubtreeNode(nodeSelections.get(0), nodeSelections.get(1), tree);
      } else {
        throw new ParseException("Illegal number of nodes given to createSubtree (" + nodeSelections.size() + ")");
      }
    }
| operator = <ADJOIN> tree = TreeRoot(true) child1 = NodeSelection()/*@bgen(jjtree)*/
    {
      jjtree.closeNodeScope(jjtn000, true);
      jjtc000 = false;
    }
/*@egen*/
    { return new AdjoinNode(tree, child1); }
| operator = <ADJOIN_TO_HEAD> tree = TreeRoot(true) child1 = NodeSelection()/*@bgen(jjtree)*/
    {
      jjtree.closeNodeScope(jjtn000, true);
      jjtc000 = false;
    }
/*@egen*/
    { return new AdjoinToHeadNode(tree, child1); }
| operator = <ADJOIN_TO_FOOT> tree = TreeRoot(true) child1 = NodeSelection()/*@bgen(jjtree)*/
    {

View on GitHub (pinned to 1b7edd19c4)