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
- Log/inspect the offending token's segment list to see why potentialSuffix and potentialPrefix diverge
- Validate segmentation output (prefix/suffix segments contiguous) before calling getHeadBounds
- Fix or update the prefix/suffix stripping rules for the morphology pattern that triggers the collision
- 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
- Log segment lists for tokens that trigger the error and compare against known morphology patterns
- Validate segmentation output contiguity before head extraction
- Patch prefix/suffix stripping rules for unsupported clitic combinations
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
- oldTag starts with B, entity at position should not be null
- Unknown minimizer: {minimizer}
- Unknown clique: " + clique
- Bad number put into wordToNumber. Word is: \"" + input + "\
- Error in wordToNumber function.
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)