{"record":{"id":"0d943ae0aed67ddd","repo":"stanfordnlp/CoreNLP","slug":"null-node-fetched-by-tsurgeon-operation-for-node","errorCode":null,"errorMessage":"Null node fetched by Tsurgeon operation for node: ","messagePattern":"Null node fetched by Tsurgeon operation for node: ","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/edu/stanford/nlp/trees/tregex/tsurgeon/FetchNode.java","lineNumber":41,"sourceCode":"  public TsurgeonMatcher matcher(Map<String,Tree> newNodeNames, CoindexationGenerator coindexer) {\n    return new Matcher(newNodeNames, coindexer);\n  }\n\n\n  private class Matcher extends TsurgeonMatcher {\n\n    public Matcher(Map<String,Tree> newNodeNames, CoindexationGenerator coindexer) {\n      super(FetchNode.this, newNodeNames, coindexer);\n    }\n\n    @Override\n    public Tree evaluate(Tree tree, TregexMatcher tregex) {\n      Tree result = newNodeNames.get(label);\n      if (result == null) {\n        result = tregex.getNode(label);\n      }\n      if (result == null) {\n        log.warn(\"Null node fetched by Tsurgeon operation for node: \" + label +\n                           \" (either no node labeled this, or the labeled node didn't match anything)\");\n      }\n      return result;\n    }\n\n  } // end class Matcher\n\n}\n","sourceCodeStart":23,"sourceCodeEnd":50,"githubUrl":"https://github.com/stanfordnlp/CoreNLP/blob/1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a/src/edu/stanford/nlp/trees/tregex/tsurgeon/FetchNode.java#L23-L50","documentation":"FetchNode is a Tsurgeon operation that fetches a tree node by a name assigned via a tregex named binding (e.g. `NP=node`). In evaluate(), if neither the new-node names map nor the tregex matcher has a node for the label, it logs this warning and returns null, so downstream Tsurgeon operations receive a null node. The library does not throw; it degrades to a warning because a named node may legitimately not have matched on some matches.","triggerScenarios":"Running a Tsurgeon script whose operation references a label (e.g. `delete foo` or `prune bar`) where the corresponding tregex pattern either never named a node with that label (`=foo` missing) or the named sub-pattern matched nothing for the current match, e.g. via Tsurgeon.processPatternsOnTree with a mismatched label between tregex and tsurgeon strings.","commonSituations":"Typo in the label between the tregex and tsurgeon parts of a paired script; a tregex using optional/alternative branches where the named node only exists on some branches; editing a tsurgeon file after changing the tregex pattern; running tsurgeon on trees where the expected constituent never appears.","solutions":["Check that every node referenced in the tsurgeon operation is bound in the tregex pattern with =label and that the label spelling matches exactly (case-sensitive).","Restructure the tregex so the named node is on a required (non-optional) part of the pattern, or add a guard so the tsurgeon only runs when the named node matched.","Enable tregex/tsurgeon debug logging and test the tregex alone against a sample tree to confirm the named node is found.","Treat the null return defensively in custom code around Tsurgeon by checking the resulting tree for null after processing."],"exampleFix":"// before: label mismatch between pattern and operation\ntregex: NP < /NN.*/\ntsurgeon: delete np\n\n// after: bind and reference the same label\ntregex: NP=np < /NN.*/\ntsurgeon: delete np","handlingStrategy":"validation","validationCode":"// Verify the tsurgeon label is bound in the tregex before processing\nString tregex = \"NP=np < /NN.*/\";\nString tsurgeon = \"delete np\";\nString label = tsurgeon.replaceAll(\"^[a-z]+\\\\s+\", \"\");\nif (!tregex.contains(\"=\" + label)) {\n  throw new IllegalStateException(\"tsurgeon references unbound label: \" + label);\n}","typeGuard":"Tree result = op.evaluate(tree, matcher);\nif (result == null) {\n  // label did not bind; skip or log\n  return null;\n}","tryCatchPattern":null,"preventionTips":["Keep the tregex and tsurgeon strings adjacent in the same script file so label changes stay in sync.","Test the tregex alone with TregexPattern against a representative tree before adding the tsurgeon operation.","Prefer required named groups over optional branches when a tsurgeon operation depends on the named node.","Enable tregex debug logging in CI to catch unbound labels early."],"tags":["tregex","tsurgeon","null-node","pattern-mismatch","nlp"],"backgroundTag":"resource-not-found","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"}