stanfordnlp/CoreNLP · error · RuntimeException
Between when the outgoing edge was found and now, the edge w
Error message
Between when the outgoing edge was found and now, the edge was somehow deleted
What it means
SetPhraseHead.evaluate() first locates the outgoing edge from the old head, rebuilds it with a new target, and calls SemanticGraph.removeEdge(). If removeEdge returns false, the edge it just found is no longer present in the graph, so the ssurgeon rule aborts with this RuntimeException. It is an internal consistency check: within a single evaluate() pass no other code should have removed the edge.
Solutions
- Re-run the semgrex match on the current graph immediately before applying SetPhraseHead so the edge references are fresh
- Ensure only one ssurgeon operation mutates the graph at a time; do not remove edges concurrently or between lookup and removal
- Check for duplicated application of the same Ssurgeon rule (idempotence) and guard with a 'modified' flag before re-running
- If using a custom SemanticGraph subclass, verify removeEdge correctly matches edges by identity/equality
Example fix
// before: edge collected in an earlier pass
for (SemanticGraphEdge e : oldEdges) { sg.removeEdge(e); }
// after: re-locate the edge on the live graph before removing
SemanticGraphEdge edgeOut = sg.getEdge(oldHead, target, reln);
if (edgeOut != null) sg.removeEdge(edgeOut); Defensive patterns
Strategy: try-catch
Validate before calling
// before evaluate: verify the edge still exists
SemanticGraphEdge e = sg.getEdge(oldHead, target, reln);
if (e == null) { reRunSemgrexMatch(sg); } Try / catch
try { op.evaluate(sg, sm); } catch (RuntimeException e) { if (e.getMessage().contains("edge was somehow deleted")) { sm = pattern.matcher(sg); /* rematch and retry once */ } else { throw e; } } Prevention
- Re-run semgrex matching immediately before each mutating ssurgeon operation
- Apply each Ssurgeon rule to a graph only once (idempotence guard)
- Deep-copy the SemanticGraph before editing if the original is needed afterwards
- Avoid interleaving custom edge removals with Ssurgeon operations on the same graph
When it happens
Trigger: Calling SetPhraseHead.evaluate(sg, sm) where the SemanticGraph is mutated between edge discovery (findEdge/edge lookup) and removeEdge, or where the edge object reference does not match an edge still in the graph (e.g. duplicate evaluation over a graph that was already rewritten, or a custom graph implementation whose removeEdge fails).
Common situations: Applying the same ssurgeon operation twice to a graph without re-matching; running custom Ssurgeon edits that remove edges inside other operations sharing the same SemanticGraph; passing a SemanticGraph copy whose edge identity differs from the matched one.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Between when the incoming edge was found and now, the edge w
- Between when the internal phrase edge was found and now, the
- oldTag starts with B, entity at position should not be null
- node cliqueFeatures[n]=
- edge cliqueFeatures[n]=
AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10).
Data as JSON: /api/errors/95538d1e31b25a99.
Report an issue: GitHub.
Appendix: source
Thrown at src/edu/stanford/nlp/semgraph/semgrex/ssurgeon/SetPhraseHead.java:128
// the newHead should be the root now
Set<IndexedWord> roots = new HashSet<>(sg.getRoots());
if (!roots.contains(newHead)) {
modified = true;
for (IndexedWord other : matchedNodes) {
roots.remove(other);
}
roots.add(newHead);
}
sg.setRoots(roots);
} else if (edgeOut.getTarget() != newHead) {
SemanticGraphEdge newEdge = new SemanticGraphEdge(edgeOut.getSource(),
newHead,
edgeOut.getRelation(),
edgeOut.getWeight(),
edgeOut.isExtra());
boolean success = sg.removeEdge(edgeOut);
if (!success) {
throw new RuntimeException("Between when the outgoing edge was found and now, the edge was somehow deleted");
}
sg.addEdge(newEdge);
modified = true;
}
for (SemanticGraphEdge edge : relocateEdges) {
SemanticGraphEdge newEdge = new SemanticGraphEdge(newHead,
edge.getTarget(),
edge.getRelation(),
edge.getWeight(),
edge.isExtra());
boolean success = sg.removeEdge(edge);
if (!success) {
throw new RuntimeException("Between when the incoming edge was found and now, the edge was somehow deleted");
}
sg.addEdge(newEdge);
modified = true;
}View on GitHub (pinned to 1b7edd19c4)