languagetool-org/languagetool · error · RuntimeException
Cannot activate rule '
Error message
Cannot activate rule '
What it means
Every pattern rule must live inside a <category> element; the handler keeps the parsed category and throws this RuntimeException in prepareRule when it is null at rule creation time. Categories are how rules are grouped and toggled in the UI.
Source
Thrown at languagetool-core/src/main/java/org/languagetool/rules/patterns/PatternRuleHandler.java:905
rule.setGoalSpecific(isGoalSpecific);
if (inRuleGroup) {
rule.setSubId(StringInterner.intern(Integer.toString(subId)));
} else {
rule.setSubId("1");
}
caseSensitive = false;
for (Match m : suggestionMatches) {
rule.addSuggestionMatch(m);
}
if (phrasePatternTokens.size() <= 1) {
suggestionMatches.clear();
}
for (Match m : suggestionMatchesOutMsg) {
rule.addSuggestionMatchOutMsg(m);
}
suggestionMatchesOutMsg.clear();
if (category == null) {
throw new RuntimeException("Cannot activate rule '" + id + "', it is outside of a <category>...</category>");
}
if (defaultOff) {
rule.setDefaultOff();
}
if (defaultTempOff) {
rule.setDefaultTempOff();
}
if (url != null && url.length() > 0) {
try {
String s = url.toString();
rule.setUrl(internUrl(s));
} catch (MalformedURLException e) {
throw new RuntimeException("Could not parse URL for rule: " + rule + ": '" + url + "'", e);
}
} else if (urlForRuleGroup != null && urlForRuleGroup.length() > 0) {
try {
rule.setUrl(internUrl(urlForRuleGroup.toString()));
} catch (MalformedURLException e) {View on GitHub (pinned to 2e990059ce)
Solutions
- Wrap the rule (or rulegroup) in a <category> element with a name and id
- Copy the category element from the original file the rule came from
- For test XML fragments, add a minimal <category name="Test" id="TEST"> wrapper
Example fix
// before <rule id="X" name="x">...</rule> // after <category id="MYCAT" name="My category"> <rule id="X" name="x">...</rule> </category>
Defensive patterns
Strategy: validation
Validate before calling
// Ensure every top-level rule/rulegroup is inside a category
NodeList rules = doc.getElementsByTagName("rule");
for (int i = 0; i < rules.getLength(); i++) {
Node p = rules.item(i).getParentNode();
boolean inCategory = false;
while (p != null) { if ("category".equals(p.getNodeName())) { inCategory = true; break; } p = p.getParentNode(); }
if (!inCategory) throw new IllegalStateException("rule outside <category>: " + ((Element) rules.item(i)).getAttribute("id"));
} Try / catch
try { loader.parse(ruleXml, lang); } catch (RuntimeException e) { if (e.getMessage().contains("outside of a <category>")) { log.error("Wrap rule in a <category> element"); } throw e; } Prevention
- Always author rules inside <category> wrappers
- When extracting rules for tests, copy the category too
- Validate structure with the official rules DTD/schema
When it happens
Trigger: Parsing a rule XML where <rule> (or <rulegroup>) appears at top level without an enclosing <category>...</category>.
Common situations: Extracting a single rule into a standalone test XML without copying its category; concatenating rule files and dropping the category wrapper.
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 '
- Neither '<pattern>' tokens nor '<regexp>' is set in rule '
- '<marker>' may not be nested in rule '
- <antipattern>s can only contain <example>s without errors (i
- <regexp> rules currently cannot be used together with <antip
AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06).
Data as JSON: /api/errors/141840f28ea6fa99.
Report an issue: GitHub.