stanfordnlp/CoreNLP · error · UnsupportedOperationException
Unknown position in AddDep: |${position}|
Error message
Unknown position in AddDep: |${position}| What it means
At evaluation time AddDep switches on the stored position string to compute the new node's index; if the position is a non-null value that was not one of the recognized signed-offset forms (or a legacy value the switch no longer handles), evaluate throws this UnsupportedOperationException. Unlike error 976, this fires at runtime during Ssurgeon execution, indicating a position format the constructor did not reject but evaluate cannot interpret.
Solutions
- Change the position to a recognized signed form: negative (insert before target), positive (insert after target), or null for default end placement.
- Re-check the Ssurgeon rule file: the exception prints the raw position between pipes (|value|), which usually reveals whitespace or an unexpected literal.
- Update to a CoreNLP version whose AddDep constructor rejects the bad position up front (error 976) instead of failing at evaluate time.
- Catch UnsupportedOperationException in the Ssurgeon driver and log the failing rule plus position for the rule author.
Example fix
// before
new AddDep("gov", rel, attrs, "0"); // parses, fails in evaluate()
// after
new AddDep("gov", rel, attrs, null); // default placement, or "+1"/"-1" Defensive patterns
Strategy: try-catch
Validate before calling
if (position != null && !(position.startsWith("-") || position.startsWith("+"))) position = null; // fall back to default placement Try / catch
try { addDep.evaluate(sg, match, env); } catch (UnsupportedOperationException e) { log.error("AddDep bad position: {}", addDep); throw e; } Prevention
- Restrict positions to null or -N/+N strings
- Log the raw |position| from the exception message to spot whitespace or literals in rule files
- Upgrade CoreNLP so bad positions are rejected at construction time (SsurgeonParseException) instead of at evaluate time
- Add a smoke test that evaluates every shipped Ssurgeon rule on a sample graph
When it happens
Trigger: Executing an AddDep operation whose position string reaches the else-branch of the index computation in evaluate() — e.g. a position like "0", " ", or a format accepted upstream but not matched by any case in the switch, on a graph where target.index() arithmetic cannot apply.
Common situations: Mixing Ssurgeon rule versions where position semantics changed; positions built programmatically as unsigned or descriptive strings; rules migrated between CoreNLP versions with different accepted position values.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- LogPrior.getSigmaSquaredM is undefined for any prior but MUL
- If you want to ask for the probability, you must train a Pla
- : Does not support parse operation.
- Cannot set from string
- Cannot set from string
AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10).
Data as JSON: /api/errors/6d656eb155bcdf24.
Report an issue: GitHub.
Appendix: source
Thrown at src/edu/stanford/nlp/semgraph/semgrex/ssurgeon/AddDep.java:126
tempIndex = SemanticGraphUtils.maxIndex(sg) + 2;
if (position.equals("-")) {
newIndex = SemanticGraphUtils.minIndex(sg);
} else if (position.startsWith("-") || position.startsWith("+")) {
String targetName = position.substring(1);
IndexedWord target = sm.getNode(targetName);
if (target == null) {
return false;
}
if (position.startsWith("-")) {
// it will be exactly to the left rather than pushing over
// something a word earlier if we do .index(), not .index() - 1
newIndex = target.index();
} else {
newIndex = target.index() + 1;
}
} else {
throw new UnsupportedOperationException("Unknown position in AddDep: |" + position + "|");
}
} else {
tempIndex = SemanticGraphUtils.maxIndex(sg) + 1;
newIndex = -1;
}
newNode.setDocID(govNode.docID());
newNode.setIndex(tempIndex);
newNode.setSentIndex(govNode.sentIndex());
sg.addVertex(newNode);
sg.addEdge(govNode, newNode, relation, weight, false);
if (position != null && !position.equals("+")) {
// the payoff for tempIndex == maxIndex + 2:
// everything will be moved one higher, unless it's the new node
SsurgeonUtils.moveNodes(sg, sm, x -> (x >= newIndex && x != tempIndex), x -> x+1, true);
SsurgeonUtils.moveNode(sg, sm, newNode, newIndex);View on GitHub (pinned to 1b7edd19c4)