stanfordnlp/CoreNLP · error · RuntimeException

Suffix pointer moved too far!

Error message

Suffix pointer moved too far!

What it means

getHeadBounds locates the head (non-prefix, non-suffix core) of a segmented Arabic word. When the computed potentialSuffix pointer lands before potentialPrefix, the code expects them to be exactly one position apart (the degenerate no-head case); otherwise it throws RuntimeException('Suffix pointer moved too far!'), signaling an internal invariant violation in the prefix/suffix stripping logic.

Solutions

  1. Log/inspect the offending token's segment list to see why potentialSuffix and potentialPrefix diverge
  2. Validate segmentation output (prefix/suffix segments contiguous) before calling getHeadBounds
  3. Fix or update the prefix/suffix stripping rules for the morphology pattern that triggers the collision
  4. Report/patch the invariant violation in IOBUtils if it is a genuine library bug

Example fix

// before
Pair<Integer,Integer> p = IOBUtils.getHeadBounds(segments, ...); // throws on bad input
// after
if (potentialSuffix < potentialPrefix && potentialSuffix + 1 != potentialPrefix) {
  // sanitize: collapse to empty head instead of throwing
  return Pair.makePair(potentialPrefix, potentialPrefix);
}
Defensive patterns

Strategy: validation

Validate before calling

// ensure prefix/suffix segments do not overlap before head extraction
if (potentialSuffix < potentialPrefix && potentialSuffix + 1 != potentialPrefix) {
  throw new IllegalStateException("Malformed segmentation for token");
}

Try / catch

try { Pair<Integer,Integer> p = IOBUtils.getHeadBounds(...); } catch (RuntimeException e) { /* log offending token segments */ }

Prevention

When it happens

Trigger: Calling headBounds/getHeadBounds on a token whose computed prefix/suffix pointers are inconsistent — e.g. morphological analysis produced overlapping prefix/suffix segments so the suffix index skipped past the prefix boundary by more than one.

Common situations: Corrupted or non-conforming segmentation output fed to the head-extraction utility; a bug or unsupported morphology case where the prefix/suffix tables (e.g. attached al-/w-/b- combinations) make pointers collide.

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


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

Appendix: source

Thrown at src/edu/stanford/nlp/international/arabic/process/IOBUtils.java:660

        if (arPrefixSet.contains(segments.get(potentialPrefix)))
          potentialPrefix++;
        else
          nonPrefix = potentialPrefix;
      }
      if (potentialSuffix < potentialPrefix || (nonSuffix != NOT_FOUND && nonPrefix != NOT_FOUND))
        break;
    }
    
    /* Once we have exhausted all known prefixes and suffixes, take the longest
     * segment that remains to be the head. Break length ties by picking the first one.
     * 
     * Note that in some cases, no segments will remain (e.g. b# +y), so a
     * segmented word may have zero or one heads, but never more than one.
     */
    if (potentialSuffix < potentialPrefix) {
      // no head--start and end are index of first suffix
      if (potentialSuffix + 1 != potentialPrefix)
        throw new RuntimeException("Suffix pointer moved too far!");
      return Pair.makePair(potentialSuffix + 1, potentialSuffix + 1);
    } else {
      int headIndex = nonPrefix;
      for (int i = nonPrefix + 1; i <= nonSuffix; i++) {
        if (segments.get(i).length() > segments.get(headIndex).length())
          headIndex = i;
      }
      return Pair.makePair(headIndex, headIndex + 1);
    }
  }

  private static boolean addPrefixMarker(int focus, List<CoreLabel> labeledSequence) {
    return labeledSequence.get(focus).get(PrefixMarkerAnnotation.class).booleanValue();
  }

  private static boolean addSuffixMarker(int focus, List<CoreLabel> labeledSequence) {
    return labeledSequence.get(focus).get(SuffixMarkerAnnotation.class).booleanValue();
  }

View on GitHub (pinned to 1b7edd19c4)