stanfordnlp/CoreNLP · error · SsurgeonParseException

Cannot make a MergeNodes out of fewer than 2 nodes (got " +…

Error message

Cannot make a MergeNodes out of fewer than 2 nodes (got " + argsBox.nodes.size() + ")

What it means

Ssurgeon's parseEditLine builds a MergeNodes edit from a semgrex ssurgeon resource line. A MergeNodes operation merges two or more matched nodes into one, so the parser requires at least 2 -node entries on the edit line. If fewer are given, it throws SsurgeonParseException before constructing the edit.

Solutions

  1. Add at least two -node:NAME arguments naming nodes matched by the semgrex query
  2. Verify the node names exist in the preceding semgrex pattern so they are captured in argsBox
  3. If you truly operate on one node, use a different edit (e.g. relabel-node, lemmatize) instead of merge-grams

Example fix

# before
ssurgeon: { dog } :: merge-grams -node:dog
# after
ssurgeon: { dog & dep(gov,dog) } :: merge-grams -node:dog -node:gov
Defensive patterns

Strategy: validation

Validate before calling

// before parsing, verify the merge line has >= 2 -node args
boolean validMerge(String line) {
  return line.startsWith("merge-grams") &&
         line.split("-node:", -1).length - 1 >= 2;
}

Try / catch

try {
  SsurgeonEdit e = Ssurgeon.parseEditLine(line);
} catch (SsurgeonParseException ex) {
  log.severe("Bad merge-grams rule: " + line + " -> " + ex.getMessage());
}

Prevention

When it happens

Trigger: An ssurgeon edit line like 'merge-grams -node:foo' with only one -node argument (or none) is parsed via Ssurgeon.parseEditLine; argsBox.nodes.size() < 2 throws.

Common situations: Hand-written ssurgeon rule files where the author forgot the second -node, or a rule generator emitted a merge with only one node (e.g. after filtering removed a node name).

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at src/edu/stanford/nlp/semgraph/semgrex/ssurgeon/Ssurgeon.java:651

        return new DeleteGraphFromNode(argsBox.nodes.get(0));
      } else if (command.equalsIgnoreCase(DeleteLeaf.LABEL)) {
        if (argsBox.nodes.size() != 1) {
          throw new SsurgeonParseException("Cannot make a DeleteLeaf out of " + argsBox.nodes.size() + " nodes");
        }
        return new DeleteLeaf(argsBox.nodes.get(0));
      } else if (command.equalsIgnoreCase(EditNode.LABEL)) {
        if (argsBox.nodes.size() != 1) {
          throw new SsurgeonParseException("Cannot make an EditNode out of " + argsBox.nodes.size() + " nodes.  Please use exactly one -node");
        }
        return new EditNode(argsBox.nodes.get(0), argsBox.annotations, argsBox.updateMorphoFeatures, argsBox.remove, argsBox.removeMorphoFeatures);
      } else if (command.equalsIgnoreCase(Lemmatize.LABEL)) {
        if (argsBox.nodes.size() != 1) {
          throw new SsurgeonParseException("Cannot make a Lemmatize out of " + argsBox.nodes.size() + " nodes.  Please use exactly one -node");
        }
        return new Lemmatize(argsBox.nodes.get(0), language);
      } else if (command.equalsIgnoreCase(MergeNodes.LABEL)) {
        if (argsBox.nodes.size() < 2) {
          throw new SsurgeonParseException("Cannot make a MergeNodes out of fewer than 2 nodes (got " + argsBox.nodes.size() + ")");
        }
        return new MergeNodes(argsBox.nodes, argsBox.annotations);
      } else if (command.equalsIgnoreCase(RelabelNamedEdge.LABEL)) {
        if (argsBox.reln == null) {
          throw new SsurgeonParseException("Relation not specified for AddEdge");
        }
        GrammaticalRelation reln = GrammaticalRelation.valueOf(language, argsBox.reln);
        return new RelabelNamedEdge(argsBox.edge, reln);
      } else if (command.equalsIgnoreCase(RemoveEdge.LABEL)) {
        GrammaticalRelation reln = null;
        if (argsBox.reln != null) {
          reln = GrammaticalRelation.valueOf(argsBox.reln);
        }
        return new RemoveEdge(reln, argsBox.govNodeName, argsBox.dep);
      } else if (command.equalsIgnoreCase(RemoveNamedEdge.LABEL)) {
        return new RemoveNamedEdge(argsBox.edge);
      } else if (command.equalsIgnoreCase(KillAllIncomingEdges.LABEL)) {
        if (argsBox.nodes.size() != 1) {

View on GitHub (pinned to 1b7edd19c4)