languagetool-org/languagetool · error · RuntimeException
Could not find rule '${ruleId}' for language ${language} in
Error message
Could not find rule '${ruleId}' for language ${language} in files: ${filenames} What it means
PatternRuleXmlCreator.toXML() throws this RuntimeException when it searched all known rule XML files for the language but found no rulegroup matching the given rule id. It is a lookup failure: the id does not exist (or is misspelled) in any of the listed files. The message includes the exact filenames searched.
Source
Thrown at languagetool-core/src/main/java/org/languagetool/rules/patterns/PatternRuleXmlCreator.java:79
NodeList ruleGroupNodes = (NodeList) xpath.evaluate("/rules/category/rulegroup[@id='" + ruleId.getId() + "']/rule", doc, XPathConstants.NODESET);
if (ruleGroupNodes != null) {
for (int i = 0; i < ruleGroupNodes.getLength(); i++) {
if (Integer.toString(i+1).equals(ruleId.getSubId())) {
return nodeToString(ruleGroupNodes.item(i));
}
}
}
} else {
Node ruleGroupNode = (Node) xpath.evaluate("/rules/category/rulegroup[@id='" + ruleId.getId() + "']", doc, XPathConstants.NODE);
if (ruleGroupNode != null) {
return nodeToString(ruleGroupNode);
}
}
} catch (Exception e) {
throw new RuntimeException("Could not turn rule '" + ruleId + "' for language " + language + " into a string", e);
}
}
throw new RuntimeException("Could not find rule '" + ruleId + "' for language " + language + " in files: " + filenames);
}
private Document getDocument(InputStream is) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
DOMImplementationLS impl = (DOMImplementationLS)registry.getDOMImplementation("LS");
LSParser parser = impl.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, null);
// we need to ignore whitespace here so the nodeToString() method will be able to indent it properly:
parser.setFilter(new IgnoreWhitespaceFilter());
LSInput domInput = impl.createLSInput();
domInput.setByteStream(is);
return parser.parse(domInput);
}
private String nodeToString(Node node) {
StringWriter sw = new StringWriter();
try {
Transformer t = TransformerFactory.newInstance().newTransformer();
t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");View on GitHub (pinned to 2e990059ce)
Solutions
- Check the filenames listed in the message and grep them for the exact rule id to see if it exists.
- Correct the rule id spelling and case to match the rulegroup @id attribute in the XML.
- Confirm you pass the correct Language so the right set of grammar files is searched.
- If the rule was removed/renamed in an upgrade, update to the new id or pin your LanguageTool version.
Example fix
// before
String xml = creator.toXML(new RuleId("UPPERCASE_I"), new English());
// after
String xml = creator.toXML(new RuleId("UPPERCASE_SENTENCE_START"), new English()); // use exact @id Defensive patterns
Strategy: validation
Validate before calling
// verify the id exists in the language's grammar files before calling
boolean exists = grammarFiles.stream()
.anyMatch(f -> fileContent(f).contains("rulegroup id=\"" + ruleId.getId() + "\""));
if (!exists) throw new IllegalArgumentException("Unknown rule id: " + ruleId.getId()); Try / catch
try {
xml = creator.toXML(ruleId, language);
} catch (RuntimeException e) {
logger.warn("Rule not found: " + ruleId.getId() + " (" + e.getMessage() + ")");
} Prevention
- Copy rule ids directly from the XML @id attribute; watch case sensitivity.
- Confirm the Language matches where the rule is defined.
- After LanguageTool upgrades, re-check ids that may have been renamed.
- Grep the grammar files listed in the message before debugging further.
When it happens
Trigger: toXML(ruleId, language) where /rules/category/rulegroup[@id='...'] matches no node in any file, including test testToXMLInvalidRuleId and the xml() helper.
Common situations: Typo in the rule id; rule exists in a different language's file; rule was renamed/removed in a LanguageTool upgrade; passing the rulegroup name vs. category vs. rule id inconsistently; case-sensitivity mismatch in ids.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Cannot load or parse input stream of '${filename}'
- Could not turn rule '${ruleId}' for language ${language} int
- WrongParameterNumberException
- listUnknownWords is set to false, unknown words not stored
- Unknown mode: <mode>
AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06).
Data as JSON: /api/errors/6f2a038eab92bc4c.
Report an issue: GitHub.