languagetool-org/languagetool · error · SAXException
You cannot set both 'chunk' and 'chunk_re' for + id
Error message
You cannot set both 'chunk' and 'chunk_re' for + id
What it means
XMLRuleHandler throws this SAXException when a token element specifies both a 'chunk' attribute and a 'chunk_re' attribute. 'chunk' matches a chunk tag literally while 'chunk_re' treats it as a regular expression; setting both is ambiguous, so rule loading fails with the rule id in the message. Pick exactly one form per token.
Source
Thrown at languagetool-core/src/main/java/org/languagetool/rules/patterns/XMLRuleHandler.java:532
tokenNegated = YES.equals(attrs.getValue(NEGATE));
tokenInflected = YES.equals(attrs.getValue(INFLECTED));
if (attrs.getValue(SKIP) != null) {
skipPos = Integer.parseInt(attrs.getValue(SKIP));
}
if (attrs.getValue(MIN) != null) {
minOccurrence = Integer.parseInt(attrs.getValue(MIN));
}
if (attrs.getValue(MAX) != null) {
maxOccurrence = Integer.parseInt(attrs.getValue(MAX));
}
elements = new StringBuilder();
if (attrs.getValue(POSTAG) != null) {
posToken = StringInterner.intern(attrs.getValue(POSTAG));
posRegExp = YES.equals(attrs.getValue(POSTAG_REGEXP));
posNegation = YES.equals(attrs.getValue(NEGATE_POS));
}
if (attrs.getValue(CHUNKTAG) != null && attrs.getValue(CHUNKTAG_REGEXP) != null) {
throw new SAXException("You cannot set both 'chunk' and 'chunk_re' for " + id);
}
if (attrs.getValue(CHUNKTAG) != null) {
chunkTag = new ChunkTag(StringInterner.intern(attrs.getValue(CHUNKTAG)));
} else if (attrs.getValue(CHUNKTAG_REGEXP) != null) {
chunkTag = new ChunkTag(StringInterner.intern(attrs.getValue(CHUNKTAG_REGEXP)), true);
}
regExpression = YES.equals(attrs.getValue(REGEXP));
if (attrs.getValue(SPACEBEFORE) != null) {
tokenSpaceBefore = YES.equals(attrs.getValue(SPACEBEFORE));
tokenSpaceBeforeSet = !IGNORE.equals(attrs.getValue(SPACEBEFORE));
}
if (!inAndGroup && !inOrGroup) {
tokenCounter++;
}
if (attrs.getValue(CASE_SENSITIVE) != null) {
tokenLevelCaseSet = true;
tokenLevelCaseSensitive = YES.equals(attrs.getValue(CASE_SENSITIVE));
} else {View on GitHub (pinned to 2e990059ce)
Solutions
- Delete one of the two attributes — keep 'chunk' for literal matching or 'chunk_re' for regex
- If you need alternation, express it in chunk_re (e.g. chunk_re="NP|PP") rather than combining attributes
- Add a schema/lint check in CI for tokens carrying both attributes
Example fix
// before <token chunk="NP" chunk_re="N.*"/> // after <token chunk_re="N.*"/>
Defensive patterns
Strategy: validation
Validate before calling
// Pre-parse check
NodeList tokens = doc.getElementsByTagName("token");
for (int i = 0; i < tokens.getLength(); i++) {
Element t = (Element) tokens.item(i);
if (t.hasAttribute("chunk") && t.hasAttribute("chunk_re")) {
throw new IllegalArgumentException("Token " + i + " sets both chunk and chunk_re");
}
} Try / catch
try {
loader.getRules(is, filename);
} catch (SAXException e) {
if (e.getMessage().startsWith("You cannot set both 'chunk' and 'chunk_re'")) {
log.error("Keep only one of chunk/chunk_re per token", e);
} else throw e;
} Prevention
- Set exactly one of chunk / chunk_re per token
- Use chunk_re alone when alternation is needed
- Lint rule XML before committing
When it happens
Trigger: Parsing a token like <token chunk="NP" chunk_re="N.*"/> in setToken — both CHUNKTAG and CHUNKTAG_REGEXP attribute values are non-null and the handler throws before building the ChunkTag.
Common situations: Migrating rules where one attribute was added without removing the other; copy-paste from two rule examples; templated rule generation merging both options.
Related errors
- References cannot be empty: Line: ${pLocator.getLineNumber
- References must be larger than 0: ${attrs.getValue("no")} L
- Only backward references in match elements are possible, tri
- Please set min and max attributes on the first token in the
- <antipattern>s can only contain <example>s without errors (i
AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06).
Data as JSON: /api/errors/e8ea4a6376576411.
Report an issue: GitHub.