stanfordnlp/CoreNLP · error · RuntimeException
Invalid match group for entry
Error message
Invalid match group for entry ${entry} What it means
During createPatternMatcher, each mapping entry's declared 'group' column is validated against the compiled TokenSequencePattern's total group count; if annotateGroup < 0 or exceeds pattern.getTotalGroups(), a RuntimeException naming the entry is thrown. It means the mapping file asks to annotate a capture group the pattern never defines.
Solutions
- Reduce the 'group' column value on the offending entry to a group that exists in the pattern (0 or 1 for single-group patterns).
- Add a capture group to the pattern so the requested group index exists.
- Remove the 'group' column from the row to fall back to the default group 0.
- Re-run and read the entry name in the message to locate the exact mapping-file line.
Example fix
// mapping file before (pattern has no group 2)
[ { word:/CEO/ } ] group=2
// after
[ { word:/CEO/ } ] group=0 Defensive patterns
Strategy: validation
Validate before calling
// Before loading: verify each group value fits its pattern's group count
int groups = countCaptureGroups(patternText); // e.g. count unescaped '(' opening groups
if (groupValue < 0 || groupValue > groups) throw new IllegalArgumentException("group " + groupValue + " invalid for pattern: " + patternText); Try / catch
try { annotator = new TokensRegexNERAnnotator(name, props); } catch (RuntimeException e) { if (e.getMessage().startsWith("Invalid match group")) { fixMappingFile(e.getMessage()); } else throw e; } Prevention
- Count capture groups in each pattern before assigning its group column
- Omit the group column when you only need the full match (default 0)
- Keep a small unit test that constructs the annotator against the shipped mapping file in CI
When it happens
Trigger: A mapping file row has a 'group' value of e.g. 2 while its pattern contains only one parenthesized group; or a negative group value is written in the group column.
Common situations: Copying a pattern from another entry and forgetting to update the group column; editing a pattern to remove a capture group while leaving group=2; hand-written regexes in TokensRegex mapping files where counting groups off by one.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- Duplicate header field:
- TokensRegexNERAnnotator ERROR: Header does not contain…
- TokensRegexNERAnnotator ERROR: Header does not contain…
- TokensRegexNERAnnotator ERROR: Invalid group in line in…
- TokensRegexNERAnnotator ERROR: Invalid priority in line in…
AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10).
Data as JSON: /api/errors/cfa3fc85073f59cb.
Report an issue: GitHub.
Appendix: source
Thrown at src/edu/stanford/nlp/pipeline/TokensRegexNERAnnotator.java:391
if (entry.tokensRegex != null) {
// TODO: posTagPatterns...
pattern = TokenSequencePattern.compile(env, entry.tokensRegex);
} else {
List<SequencePattern.PatternExpr> nodePatterns = new ArrayList<>(entry.regex.length);
for (String p:entry.regex) {
CoreMapNodePattern c = CoreMapNodePattern.valueOf(p, patternFlags);
if (posTagPattern != null) {
c.add(CoreAnnotations.PartOfSpeechAnnotation.class, posTagPattern);
}
nodePatterns.add(new SequencePattern.NodePatternExpr(c));
}
if (nodePatterns.size() == 1) {
nodePatterns = Collections.singletonList(nodePatterns.get(0));
}
pattern = TokenSequencePattern.compile(new SequencePattern.SequencePatternExpr(nodePatterns));
}
if (entry.annotateGroup < 0 || entry.annotateGroup > pattern.getTotalGroups()) {
throw new RuntimeException("Invalid match group for entry " + entry);
}
pattern.setPriority(entry.priority);
pattern.setWeight(entry.weight);
patterns.add(pattern);
patternToEntry.put(pattern, entry);
}
return TokenSequencePattern.getMultiPatternMatcher(patterns);
}
private void annotateMatched(List<CoreLabel> tokens) {
List<SequenceMatchResult<CoreMap>> matched = multiPatternMatcher.findNonOverlapping(tokens);
for (SequenceMatchResult<CoreMap> m:matched) {
Entry entry = patternToEntry.get(m.pattern());
// Check if we will overwrite the existing annotation with this annotation
int g = entry.annotateGroup;
int start = m.start(g);
int end = m.end(g);View on GitHub (pinned to 1b7edd19c4)