stanfordnlp/CoreNLP · error · RuntimeException

Invalid start index =-: originalSpan=[], head=

Error message

Invalid start index =-: originalSpan=[], head=

What it means

The Mention constructor throws when computing the NE-suffix scan: the head word's offset within originalSpan (headIndex - startIndex) is negative or >= originalSpan.size(), meaning the head word is not inside the mention's original span. This catches a broken span/head alignment early.

Solutions

  1. Fix the code that sets startIndex/headIndex so headIndex lies within [startIndex, startIndex+originalSpan.size())
  2. Verify originalSpan is built from the same CoreMap token list used for headIndex
  3. Validate mention spans before construction: assert headIndex >= startIndex && headIndex < startIndex + span.size()
  4. If constructing mentions from external parses, recompute headIndex using CoreNLP's head-finder conventions

Example fix

// before
int start = headIndex - startIndex;
Mention m = new Mention(..., originalSpan, headWord, ...); // start out of range
// after
if (headIndex < startIndex || headIndex - startIndex >= originalSpan.size()) {
  throw new IllegalArgumentException("head outside span: " + headIndex + "/" + startIndex);
}
Mention m = new Mention(..., originalSpan, headWord, ...);
Defensive patterns

Strategy: validation

Validate before calling

boolean valid = headIndex >= startIndex
  && originalSpan.size() > 0
  && (headIndex - startIndex) < originalSpan.size();
if (!valid) throw new IllegalArgumentException("head word outside mention span");

Try / catch

try {
  Mention m = new Mention(id, sentNum, startIndex, endIndex, animacy, generics, ...);
} catch (RuntimeException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("Invalid start index")) {
    logger.severe("Head/span misalignment in custom mention extraction: " + e.getMessage());
  } else throw e;
}

Prevention

When it happens

Trigger: Building new Mention(..., originalSpan, headWord, ...) where headIndex < startIndex or headIndex - startIndex >= originalSpan.size(), for a mention whose head word has a NamedEntityTag other than 'O'.

Common situations: Custom mention-extraction code computing headIndex from a different token list than originalSpan; off-by-one span construction (end-exclusive vs end-inclusive); downstream tools constructing Mentions from parse output with mismatched indices.

Related errors


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

Appendix: source

Thrown at src/edu/stanford/nlp/coref/data/Mention.java:720

  private static boolean knownSuffix(String s) {
    if(s.endsWith(".")) s = s.substring(0, s.length() - 1);
    for(String suff: commonNESuffixes){
      if(suff.equalsIgnoreCase(s)){
        return true;
      }
    }
    return false;
  }

  private void setHeadString() {
    this.headString = headWord.get(CoreAnnotations.TextAnnotation.class).toLowerCase();
    String ner = headWord.get(CoreAnnotations.NamedEntityTagAnnotation.class);
    if (ner != null && !ner.equals("O")) {
      // make sure that the head of a NE is not a known suffix, e.g., Corp.
      int start = headIndex - startIndex;
      if (originalSpan.size() > 0 && start >= originalSpan.size()) {
        throw new RuntimeException("Invalid start index " + start + "=" + headIndex + "-" + startIndex
                + ": originalSpan=[" + StringUtils.joinWords(originalSpan, " ") + "], head=" + headWord);
      }
      while (start >= 0) {
        String head = originalSpan.size() > 0 ? originalSpan.get(start).get(CoreAnnotations.TextAnnotation.class).toLowerCase() : "";
        if (knownSuffix(head)) {
          start --;
        } else {
          this.headString = head;
          this.headWord = originalSpan.get(start);
          this.headIndex = startIndex + start;
          break;
        }
      }
    }
    this.headIndexedWord = basicDependency.getNodeByIndexSafe(headWord.index());
  }

  private void setNERString() {

View on GitHub (pinned to 1b7edd19c4)