stanfordnlp/CoreNLP · error · SsurgeonParseException
-headIndex of is out of bounds for a phrase with words
Error message
-headIndex of ${headIndex} is out of bounds for a phrase with ${nodes.size()} words What it means
SetPhraseHead validates that headIndex is a 0-indexed position within the supplied node list; values below 0 or at/after nodes.size() point at no node in the phrase and the constructor throws with the actual index and list size in the message.
Solutions
- Set -headIndex to a value between 0 and (number of -node arguments - 1)
- Count the -node entries in the rule and adjust headIndex; remember it is 0-indexed
- Update headIndex whenever you add or remove nodes from the phrase
Example fix
// before
new SetPhraseHead(Arrays.asList("n1","n2"), 2, reln, 1.0); // out of bounds
// after
new SetPhraseHead(Arrays.asList("n1","n2"), 1, reln, 1.0); Defensive patterns
Strategy: validation
Validate before calling
if (headIndex != null && (headIndex < 0 || headIndex >= nodes.size())) {
throw new IllegalArgumentException("headIndex " + headIndex + " must be in [0, " + (nodes.size()-1) + "]");
} Type guard
boolean headIndexInRange(Integer idx, int numNodes) { return idx != null && idx >= 0 && idx < numNodes; } Try / catch
try {
op = new SetPhraseHead(nodes, headIndex, relation, weight);
} catch (SsurgeonParseException e) {
log.error("-headIndex out of bounds: {}", e.getMessage());
throw new RuleSyntaxException(e);
} Prevention
- Remember headIndex is 0-based; the last valid value is nodeCount - 1
- Recompute -headIndex whenever -node arguments change
- Add a rule-lint step that parses every set-phrase-head line and checks bounds
When it happens
Trigger: new SetPhraseHead(nodes, headIndex, ...) where headIndex < 0 or headIndex >= nodes.size(), e.g. headIndex 2 with a 2-node list, or an Ssurgeon line with -headIndex 1 when only one -node was given.
Common situations: Confusing 1-based and 0-based indexing in rules; adding/removing -node arguments from the rule without updating -headIndex; generating rules programmatically where the node list shrunk.
Related errors
- Unknown position in AddDep operation
- No governor given for an AddDep
- No relation given for an AddDep
- Unknown position in AddDep: |
- Cannot manually set the index attribute. If you need a…
AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10).
Data as JSON: /api/errors/52f03220afe3bde2.
Report an issue: GitHub.
Appendix: source
Thrown at src/edu/stanford/nlp/semgraph/semgrex/ssurgeon/SetPhraseHead.java:35
* If that condition is matched, then existing internal edges are replaced with edges to the new head, with the given reln <br>
* If the head is changed, the edge out of the phrase (if it is not root) is changed to come from the new head <br>
* Edges in to the phrase are also changed to point to the new head.
* The purpose of that change is so for a noun phrase, for example, modifiers of that noun phrase such as nmod or nmod:desc now modify the new head
*/
public class SetPhraseHead extends SsurgeonEdit {
public static final String LABEL = "setPhraseHead";
final List<String> phrase;
final int headIndex;
final GrammaticalRelation relation;
final double weight;
public SetPhraseHead(List<String> nodes, Integer headIndex, GrammaticalRelation relation, double weight) {
if (headIndex == null) {
throw new SsurgeonParseException("SetPhraseHead expected a -headIndex, 0-indexed for the node to use as the new head");
}
if (headIndex < 0 || headIndex >= nodes.size()) {
throw new SsurgeonParseException("-headIndex of " + headIndex + " is out of bounds for a phrase with " + nodes.size() + " words");
}
if (relation == null) {
throw new SsurgeonParseException("SetPhraseHead expected a -reln to represent the dependency to use for the new phrase");
}
this.phrase = new ArrayList<>(nodes);
this.headIndex = headIndex;
this.relation = relation;
this.weight = weight;
}
@Override
public String toEditString() {
StringWriter buf = new StringWriter();
buf.write(LABEL);
buf.write("\t");
for (String node : phrase) {View on GitHub (pinned to 1b7edd19c4)