stanfordnlp/CoreNLP · warning
Null node fetched by Tsurgeon operation for node:
Error message
Null node fetched by Tsurgeon operation for node:
What it means
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.
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.
Example fix
// before: label mismatch between pattern and operation tregex: NP < /NN.*/ tsurgeon: delete np // after: bind and reference the same label tregex: NP=np < /NN.*/ tsurgeon: delete np
Defensive patterns
Strategy: validation
Validate before calling
// Verify the tsurgeon label is bound in the tregex before processing
String tregex = "NP=np < /NN.*/";
String tsurgeon = "delete np";
String label = tsurgeon.replaceAll("^[a-z]+\\s+", "");
if (!tregex.contains("=" + label)) {
throw new IllegalStateException("tsurgeon references unbound label: " + label);
} Type guard
Tree result = op.evaluate(tree, matcher);
if (result == null) {
// label did not bind; skip or log
return null;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Error: looking for a non-existent parent in tree " + tree +
- Error: Haven't dealt with relation " + relation + " yet.
- Tsurgeon.processPatternsOnTree failed to match label for pat
- Unknown minimizer: {minimizer}
- Unknown clique: " + clique
AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10).
Data as JSON: /api/errors/0d943ae0aed67ddd.
Report an issue: GitHub.
Appendix: source
Thrown at src/edu/stanford/nlp/trees/tregex/tsurgeon/FetchNode.java:41
public TsurgeonMatcher matcher(Map<String,Tree> newNodeNames, CoindexationGenerator coindexer) {
return new Matcher(newNodeNames, coindexer);
}
private class Matcher extends TsurgeonMatcher {
public Matcher(Map<String,Tree> newNodeNames, CoindexationGenerator coindexer) {
super(FetchNode.this, newNodeNames, coindexer);
}
@Override
public Tree evaluate(Tree tree, TregexMatcher tregex) {
Tree result = newNodeNames.get(label);
if (result == null) {
result = tregex.getNode(label);
}
if (result == null) {
log.warn("Null node fetched by Tsurgeon operation for node: " + label +
" (either no node labeled this, or the labeled node didn't match anything)");
}
return result;
}
} // end class Matcher
}
View on GitHub (pinned to 1b7edd19c4)