languagetool-org/languagetool · error · IllegalStateException
'<marker>' may not be nested in rule '
Error message
'<marker>' may not be nested in rule '
What it means
LanguageTool's <marker> element marks the error span inside a pattern or example and must not be nested inside another <marker>. The SAX handler tracks inMarker and throws IllegalStateException on a second opening marker while already inside one.
Source
Thrown at languagetool-core/src/main/java/org/languagetool/rules/patterns/PatternRuleHandler.java:449
if (minPrevMatchesStr2 != null) {
ruleGroupMinPrevMatches = Integer.parseInt(minPrevMatchesStr2);
}
String distanceTokensStr2 = attrs.getValue(DISTANCETOKENS);
if (distanceTokensStr2 != null) {
ruleGroupDistanceTokens = Integer.parseInt(distanceTokensStr2);
}
antipatternForRuleGroupsExamples = new ArrayList<>();
String prioRuleGroupAttributeValue = attrs.getValue(PRIO);
if (prioRuleGroupAttributeValue != null) {
prioRuleGroupAttribute = Integer.parseInt(prioRuleGroupAttributeValue);
}
break;
case MATCH:
setMatchElement(attrs, inSuggestion && (isSuggestionSuppressMisspelled || isRuleSuppressMisspelled));
break;
case MARKER:
if (inMarker) {
throw new IllegalStateException("'<marker>' may not be nested in rule '" + id + "'");
}
if (inIncorrectExample) {
incorrectExample.append(MARKER_TAG);
} else if (inCorrectExample) {
correctExample.append(MARKER_TAG);
} else if (inErrorTriggerExample) {
errorTriggerExample.append(MARKER_TAG);
} else if (inPattern || inAntiPattern) {
startPos = tokenCounter;
inMarker = true;
}
break;
case UNIFICATION:
uFeature = attrs.getValue("feature");
inUnificationDef = true;
break;
case "equivalence":
uType = attrs.getValue(TYPE);View on GitHub (pinned to 2e990059ce)
Solutions
- Remove the outer or inner duplicate <marker> so only one nesting level remains
- Split the marked region so each span is marked once, side by side, not nested
- If marking two separate tokens, use two adjacent markers at the same level (check rule semantics) or a single wider marker
Example fix
// before <pattern><marker><token>a</token><marker><token>b</token></marker></marker></pattern> // after <pattern><marker><token>a</token><token>b</token></marker></pattern>
Defensive patterns
Strategy: validation
Validate before calling
// Reject nested markers before loading
NodeList markers = doc.getElementsByTagName("marker");
for (int i = 0; i < markers.getLength(); i++) {
if (markers.item(i).getChildNodes().getLength() > 0) {
NodeList kids = markers.item(i).getChildNodes();
for (int j = 0; j < kids.getLength(); j++)
if ("marker".equals(kids.item(j).getNodeName()))
throw new IllegalStateException("nested <marker>");
}
} Try / catch
try { loader.parse(ruleXml, lang); } catch (IllegalStateException e) { if (e.getMessage().contains("may not be nested")) { log.error("Un-nest <marker> elements"); } throw e; } Prevention
- Use exactly one <marker> level per span
- When marking several areas, place markers side by side, never nested
- Lint XML for duplicate/nested marker tags in CI
When it happens
Trigger: XML containing <marker>...<marker>...</marker>...</marker> within a rule pattern, suggestion, or example. Raised in startElement case MARKER when inMarker is already true.
Common situations: Copy-paste merging two marked spans; careless editing that wraps an existing marker in another marker; automated XML generation that emits nested markers.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- id is null for rule with name '
- <antipattern>s can only contain <example>s without errors (i
- <regexp> rules currently cannot be used together with <antip
- Neither '<pattern>' tokens nor '<regexp>' is set in rule '
- Cannot activate rule '
AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06).
Data as JSON: /api/errors/2a946fea43c026af.
Report an issue: GitHub.