stanfordnlp/CoreNLP · error · IllegalArgumentException

Span is out of range:

Error message

Span is out of range: 

What it means

headOfSpan validates the span against the sentence length via the governors list; if tokenSpan.start() >= governors.size() the span begins beyond the sentence, so IllegalArgumentException('Span is out of range') is thrown. It guards against spans referencing tokens that don't exist in this sentence.

Solutions

  1. Verify the span belongs to this exact Sentence (0-based token indices within the sentence length)
  2. Recompute spans after any re-tokenization instead of reusing old ones
  3. Check tokenSpan.start() < sentence.length() before calling

Example fix

// before
int head = algorithms.headOfSpan(otherSentenceSpan);
// after
if (span.start() >= sentence.length() || span.end() > sentence.length()) {
  throw new IllegalArgumentException("span does not belong to sentence");
}
int head = algorithms.headOfSpan(span);
Defensive patterns

Strategy: validation

Validate before calling

if (span.start() >= 0 && span.start() < sentence.length()) {
  int head = sentence.algorithms().headOfSpan(span);
}

Type guard

boolean spanInSentence(Span s, Sentence sentence) {
  return s.start() >= 0 && s.end() <= sentence.length();
}

Try / catch

try {
  int head = algorithms.headOfSpan(span);
} catch (IllegalArgumentException e) {
  if (e.getMessage().startsWith("Span is out of range")) {
    head = -1;
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling headOfSpan with a Span whose start index is >= the number of tokens in the sentence — typically a span from a different sentence, from stale indices after re-tokenization, or constructed with 1-based offsets by mistake.

Common situations: Mixing spans computed on an older tokenization of the sentence with a re-created Sentence; sharing spans across sentences in a document loop; off-by-one from passing character offsets instead of token indices.

Related errors


AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10). Data as JSON: /api/errors/dd5f90d20834aac8. Report an issue: GitHub.

Appendix: source

Thrown at src/edu/stanford/nlp/simple/SentenceAlgorithms.java:245

   */
  public List<String> keyphrases() {
    return keyphrases(Sentence::words);
  }

  /**
   * Get the index of the head word for a given span, based off of the dependency parse.
   *
   * @param tokenSpan The span of tokens we are finding the head of.
   * @return The head index of the given span of tokens.
   */
  public int headOfSpan(Span tokenSpan) {
    // Error checks
    if (tokenSpan.size() == 0) {
      throw new IllegalArgumentException("Cannot find head word of empty span!");
    }
    List<Optional<Integer>> governors = sentence.governors();
    if (tokenSpan.start() >= governors.size()) {
      throw new IllegalArgumentException("Span is out of range: " + tokenSpan + "; sentence: " + sentence);
    }
    if (tokenSpan.end() > governors.size()) {
      throw new IllegalArgumentException("Span is out of range: " + tokenSpan + "; sentence: " + sentence);
    }

    // Find where to start searching up the dependency tree
    int candidateStart = tokenSpan.end() - 1;
    Optional<Integer> parent;
    while ( !(parent = governors.get(candidateStart)).isPresent() ) {
      candidateStart -= 1;
      if (candidateStart < tokenSpan.start()) {
        // Case: nothing in this span has a head. Default to right-most element.
        return tokenSpan.end() - 1;
      }
    }
    int candidate = candidateStart;

    // Search up the dependency tree

View on GitHub (pinned to 1b7edd19c4)