{"record":{"id":"b28df46a1a27043b","repo":"stanfordnlp/CoreNLP","slug":"transformer-did-not-change-treegraphnode-into-anot","errorCode":null,"errorMessage":"Transformer did not change TreeGraphNode into another TreeGraphNode: <transformer>","messagePattern":"Transformer did not change TreeGraphNode into another TreeGraphNode: <transformer>","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/edu/stanford/nlp/trees/GrammaticalStructure.java","lineNumber":171,"sourceCode":"   *                      punctuation word strings, and true otherwise.\n   *                      If punctuation dependencies should be kept, you\n   *                      should pass in a {@code Filters.<String>acceptFilter()}.\n   * @param tagFilter     Appears to be unused (filters out tags??)\n   */\n  public GrammaticalStructure(Tree t, Collection<GrammaticalRelation> relations,\n                              Lock relationsLock, TreeTransformer transformer,\n                              HeadFinder hf, Predicate<String> puncFilter,\n                              Predicate<String> tagFilter) {\n    TreeGraphNode treeGraph = new TreeGraphNode(t, (TreeGraphNode) null);\n    // TODO: create the tree and reuse the leaf labels in one pass,\n    // avoiding a wasteful copy of the labels.\n    Trees.setLeafLabels(treeGraph, t.yield());\n    Trees.setLeafTagsIfUnset(treeGraph);\n    //System.out.println(treeGraph.toPrettyString(2));\n    if (transformer != null) {\n      Tree transformed = transformer.transformTree(treeGraph);\n      if (!(transformed instanceof TreeGraphNode)) {\n        throw new RuntimeException(\"Transformer did not change TreeGraphNode into another TreeGraphNode: \" + transformer);\n      }\n      this.root = (TreeGraphNode) transformed;\n    } else {\n      this.root = treeGraph;\n    }\n    //System.out.println(this.root.toPrettyString(2));\n    indexNodes(this.root);\n    // add head word and tag to phrase nodes\n    if (hf == null) {\n      throw new AssertionError(\"Cannot use null HeadFinder\");\n    }\n    try {\n      root.percolateHeads(hf);\n    } catch (IllegalArgumentException e) {\n      throw new IllegalArgumentException(\"Cannot process tree:\\n\" + t, e);\n    }\n    if (root.value() == null) {\n      root.setValue(\"ROOT\");  // todo: cdm: it doesn't seem like this line should be here","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/stanfordnlp/CoreNLP/blob/1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a/src/edu/stanford/nlp/trees/GrammaticalStructure.java#L153-L189","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Modify the transformer so it returns TreeGraphNode objects (e.g. by copying graph structure or building nodes via a TreeGraphNodeFactory)","Remove the transformer argument (pass null) if no transformation is actually required","Wrap the transformer's output: convert the resulting plain Tree back into a TreeGraphNode before returning","Use a transformer implementation known to be compatible with grammatical-structure construction"],"exampleFix":"// before\npublic Tree transformTree(Tree t) { return t.deepCopy(); } // plain Tree\n// after\npublic Tree transformTree(Tree t) { return new TreeGraphNode(t, tf); } // tf: TreeGraphNodeFactory","handlingStrategy":"type-guard","validationCode":"Tree out = transformer.transformTree(treeGraph);\nif (!(out instanceof TreeGraphNode)) throw new IllegalArgumentException(\"Transformer must return TreeGraphNode\");","typeGuard":"boolean isSafeTransformer(TreeTransformer t, TreeGraphNode input) {\n    return t.transformTree(input) instanceof TreeGraphNode;\n}","tryCatchPattern":"try {\n    GrammaticalStructure gs = new EnglishGrammaticalStructure(tree, puncFilter, hf, transformer);\n} catch (RuntimeException e) {\n    if (e.getMessage().startsWith(\"Transformer did not change\")) {\n        // retry without transformer (null) or fix transformer\n    } else throw e;\n}","preventionTips":["Unit-test custom transformers against TreeGraphNode inputs","Base transformers on TreeGraphNode trees so graph structure is preserved","Pass null when no transformation is needed","Document transformer contracts (must return TreeGraphNode)"],"tags":["java","transformer","type-mismatch","dependency-parsing"],"backgroundTag":"type-mismatch","analyzedSha":"1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a","analyzedAt":"2026-09-10T02:24:07.274Z","contentChangedAt":"2026-09-10T02:24:07.274Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}