stanfordnlp/CoreNLP · error · TsurgeonParseException

Error -- two foot nodes in subtree" + t.toString()

Error message

Error -- two foot nodes in subtree" + t.toString()

What it means

findFootNodeHelper recursively scans an auxiliary tree for the foot node. If more than one node in the subtree carries the foot marker, the scan finds two candidate descendants and throws TsurgeonParseException, because a foot node must be unique.

Solutions

  1. Ensure exactly one node label in the auxiliary tree contains the '@' foot marker.
  2. Scan the aux tree string for occurrences of '@' and remove all but the intended attachment-point marker.
  3. Note '@' is also an escape character in labels; if a literal '@' is needed in a label, escape it (see escapedFootNodeCharacter handling) so it is not counted as a foot.

Example fix

// before
String aux = "{@SBAR {@NP the dog}}"; // two foot markers
// after
String aux = "{@SBAR {NP the dog}}"; // exactly one foot node
Defensive patterns

Strategy: validation

Validate before calling

int countFootMarkers(String auxTreeString) {
  int count = 0;
  for (char c : auxTreeString.toCharArray()) if (c == '@') count++;
  return count; // must be exactly 1 for a valid auxiliary tree
}

Try / catch

try {
  AuxiliaryTree aux = new AuxiliaryTree(tree, true);
} catch (TsurgeonParseException e) {
  if (e.getMessage().contains("two foot nodes")) throw new IllegalArgumentException("Aux tree has multiple '@' markers: " + tree);
  throw e;
}

Prevention

When it happens

Trigger: Constructing an AuxiliaryTree whose tree labels contain the '@' foot escape on two or more nodes, e.g. '{@NP {@PP ...}}'; findFootNode calls this helper and the second found node triggers the throw.

Common situations: Hand-written Tsurgeon auxiliary trees where '@' was accidentally duplicated (e.g. applied to both a category label and a value, or copy-pasted to nested nodes); automated generation of aux trees marking every node.

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/d8a1503cea85754b. Report an issue: GitHub.

Appendix: source

Thrown at src/edu/stanford/nlp/trees/tregex/tsurgeon/AuxiliaryTree.java:162

    return result;
  }

  private static Tree findFootNodeHelper(Tree t) {
    Tree foundDtr = null;
    if (t.isLeaf()) {
      Matcher m = footNodeLabelPattern.matcher(t.label().value());
      if (m.matches()) {
        t.label().setValue(m.group(1));
        return t;
      } else {
        return null;
      }
    }
    for (Tree child : t.children()) {
      Tree thisFoundDtr = findFootNodeHelper(child);
      if (thisFoundDtr != null) {
        if (foundDtr != null) {
          throw new TsurgeonParseException("Error -- two foot nodes in subtree" + t.toString());
        } else {
          foundDtr = thisFoundDtr;
        }
      }
    }
    Matcher m = escapedFootNodeCharacter.matcher(t.label().value());
    t.label().setValue(m.replaceAll(footNodeCharacter));
    return foundDtr;
  }


  /* ******************************************************* *
   * below here is init stuff for getting node -> names maps *
   * ******************************************************* */

  // There are two ways in which you can can match the start of a name
  // expression.
  // The first is if you have any number of non-escaping characters

View on GitHub (pinned to 1b7edd19c4)