stanfordnlp/CoreNLP · error · RuntimeException

Transformer did not change TreeGraphNode into another…

Error message

Transformer did not change TreeGraphNode into another TreeGraphNode: <transformer>

What it means

The GrammaticalStructure constructor optionally applies a TreeTransformer to the TreeGraphNode it built. Since a grammatical structure's root must remain a TreeGraphNode, if the transformer returns a plain Tree (or another Tree subtype), the invariant is broken and this RuntimeException is thrown, naming the offending transformer.

Solutions

  1. Modify the transformer so it returns TreeGraphNode objects (e.g. by copying graph structure or building nodes via a TreeGraphNodeFactory)
  2. Remove the transformer argument (pass null) if no transformation is actually required
  3. Wrap the transformer's output: convert the resulting plain Tree back into a TreeGraphNode before returning
  4. Use a transformer implementation known to be compatible with grammatical-structure construction

Example fix

// before
public Tree transformTree(Tree t) { return t.deepCopy(); } // plain Tree
// after
public Tree transformTree(Tree t) { return new TreeGraphNode(t, tf); } // tf: TreeGraphNodeFactory
Defensive patterns

Strategy: type-guard

Validate before calling

Tree out = transformer.transformTree(treeGraph);
if (!(out instanceof TreeGraphNode)) throw new IllegalArgumentException("Transformer must return TreeGraphNode");

Type guard

boolean isSafeTransformer(TreeTransformer t, TreeGraphNode input) {
    return t.transformTree(input) instanceof TreeGraphNode;
}

Try / catch

try {
    GrammaticalStructure gs = new EnglishGrammaticalStructure(tree, puncFilter, hf, transformer);
} catch (RuntimeException e) {
    if (e.getMessage().startsWith("Transformer did not change")) {
        // retry without transformer (null) or fix transformer
    } else throw e;
}

Prevention

When it happens

Trigger: Passing a transformer (e.g. some SemanticHeadFinder-based or custom TreeTransformer) to the GrammaticalStructure constructor whose transformTree() returns a Tree that is not a TreeGraphNode; wrapping a structure-building pipeline with a transformer written for plain Trees.

Common situations: Custom transformers (e.g. coordinate-structure flattening, node-pruning) that build new Tree nodes instead of TreeGraphNode; reusing transformers meant for the parser pipeline inside dependency-construction code.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at src/edu/stanford/nlp/trees/GrammaticalStructure.java:171

   *                      punctuation word strings, and true otherwise.
   *                      If punctuation dependencies should be kept, you
   *                      should pass in a {@code Filters.<String>acceptFilter()}.
   * @param tagFilter     Appears to be unused (filters out tags??)
   */
  public GrammaticalStructure(Tree t, Collection<GrammaticalRelation> relations,
                              Lock relationsLock, TreeTransformer transformer,
                              HeadFinder hf, Predicate<String> puncFilter,
                              Predicate<String> tagFilter) {
    TreeGraphNode treeGraph = new TreeGraphNode(t, (TreeGraphNode) null);
    // TODO: create the tree and reuse the leaf labels in one pass,
    // avoiding a wasteful copy of the labels.
    Trees.setLeafLabels(treeGraph, t.yield());
    Trees.setLeafTagsIfUnset(treeGraph);
    //System.out.println(treeGraph.toPrettyString(2));
    if (transformer != null) {
      Tree transformed = transformer.transformTree(treeGraph);
      if (!(transformed instanceof TreeGraphNode)) {
        throw new RuntimeException("Transformer did not change TreeGraphNode into another TreeGraphNode: " + transformer);
      }
      this.root = (TreeGraphNode) transformed;
    } else {
      this.root = treeGraph;
    }
    //System.out.println(this.root.toPrettyString(2));
    indexNodes(this.root);
    // add head word and tag to phrase nodes
    if (hf == null) {
      throw new AssertionError("Cannot use null HeadFinder");
    }
    try {
      root.percolateHeads(hf);
    } catch (IllegalArgumentException e) {
      throw new IllegalArgumentException("Cannot process tree:\n" + t, e);
    }
    if (root.value() == null) {
      root.setValue("ROOT");  // todo: cdm: it doesn't seem like this line should be here

View on GitHub (pinned to 1b7edd19c4)