{"record":{"id":"18ac35e8830f18a0","repo":"languagetool-org/languagetool","slug":"could-not-turn-rule-ruleid-for-language-lan","errorCode":null,"errorMessage":"Could not turn rule '${ruleId}' for language ${language} into a string","messagePattern":"Could not turn rule '(.+?)' for language (.+?) into a string","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"languagetool-core/src/main/java/org/languagetool/rules/patterns/PatternRuleXmlCreator.java","lineNumber":76,"sourceCode":"          return nodeToString(ruleNodeInGroup);\n        }\n        if (ruleId.getSubId() != null) {\n          NodeList ruleGroupNodes = (NodeList) xpath.evaluate(\"/rules/category/rulegroup[@id='\" + ruleId.getId() + \"']/rule\", doc, XPathConstants.NODESET);\n          if (ruleGroupNodes != null) {\n            for (int i = 0; i < ruleGroupNodes.getLength(); i++) {\n              if (Integer.toString(i+1).equals(ruleId.getSubId())) {\n                return nodeToString(ruleGroupNodes.item(i));\n              }\n            }\n          }\n        } else {\n          Node ruleGroupNode = (Node) xpath.evaluate(\"/rules/category/rulegroup[@id='\" + ruleId.getId() + \"']\", doc, XPathConstants.NODE);\n          if (ruleGroupNode != null) {\n            return nodeToString(ruleGroupNode);\n          }\n        }\n      } catch (Exception e) {\n        throw new RuntimeException(\"Could not turn rule '\" + ruleId + \"' for language \" + language + \" into a string\", e);\n      }\n    }\n    throw new RuntimeException(\"Could not find rule '\" + ruleId + \"' for language \" + language + \" in files: \" + filenames);\n  }\n\n  private Document getDocument(InputStream is) throws InstantiationException, IllegalAccessException, ClassNotFoundException {\n    DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();\n    DOMImplementationLS impl = (DOMImplementationLS)registry.getDOMImplementation(\"LS\");\n    LSParser parser = impl.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, null);\n    // we need to ignore whitespace here so the nodeToString() method will be able to indent it properly:\n    parser.setFilter(new IgnoreWhitespaceFilter());\n    LSInput domInput = impl.createLSInput();\n    domInput.setByteStream(is);\n    return parser.parse(domInput);\n  }\n\n  private String nodeToString(Node node) {\n    StringWriter sw = new StringWriter();","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-core/src/main/java/org/languagetool/rules/patterns/PatternRuleXmlCreator.java#L58-L94","documentation":"PatternRuleXmlCreator.toXML() extracts a rulegroup node from the language's rule XML files via XPath and wraps any exception during that conversion in a RuntimeException('Could not turn rule ... into a string'). This branch fires when the files could be searched but serialization/XPath evaluation threw; if nothing throws but no node matches, error 94 is thrown instead.","triggerScenarios":"Calling toXML(RuleId, Language) when XPath evaluation, document parsing (getDocument), or nodeToString throws for a rule whose id exists in filenames.","commonSituations":"Rule id containing characters that break the XPath string query (quotes/brackets); DOM configuration issues (DOMImplementationRegistry failing in restricted environments like applets/GraalVM); malformed rule XML documents in the grammar directory.","solutions":["Inspect e.getCause() to find whether parsing or XPath evaluation failed, and fix that specific document/environment issue.","Ensure the rule id contains only plain characters usable inside an XPath predicate (escape or avoid quotes/apostrophes).","Verify the grammar XML files for the language parse correctly (validate with an XML tool).","Ensure the runtime supports the DOM Level 3 Load/Save implementation (not a stripped JRE/GraalVM without it)."],"exampleFix":"// before\nString xml = creator.toXML(new RuleId(\"it's-rule\"), lang);\n// after\nString xml = creator.toXML(new RuleId(\"its-rule\"), lang); // avoid quotes in rule ids","handlingStrategy":"try-catch","validationCode":"// check id is XPath-predicate-safe\nif (ruleId.getId().matches(\".*['\\[\\]].*\")) throw new IllegalArgumentException(\"Unsafe rule id: \" + ruleId.getId());","typeGuard":null,"tryCatchPattern":"try {\n  xml = creator.toXML(ruleId, language);\n} catch (RuntimeException e) {\n  logger.warn(\"XML conversion failed for \" + ruleId + \": \" + e.getCause());\n}","preventionTips":["Keep rule ids free of quotes and XPath special characters.","Run on a JVM with full DOM Level 3 Load/Save support (avoid stripped runtimes).","Validate grammar XML files parse cleanly before conversion.","Read the chained cause to distinguish parse vs. XPath failures."],"tags":["xml","xpath","serialization","java"],"backgroundTag":"json-serialization-failed","analyzedSha":"2e990059ce67d5e2a0f7f7ca5d31160c6709df4b","analyzedAt":"2026-09-06T09:20:17.015Z","contentChangedAt":"2026-09-06T09:20:17.015Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}