languagetool-org/languagetool · error · RuntimeException

Could not turn rule '${ruleId}' for language ${language} int

Error message

Could not turn rule '${ruleId}' for language ${language} into a string

What it means

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.

Source

Thrown at languagetool-core/src/main/java/org/languagetool/rules/patterns/PatternRuleXmlCreator.java:76

          return nodeToString(ruleNodeInGroup);
        }
        if (ruleId.getSubId() != null) {
          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();

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Inspect e.getCause() to find whether parsing or XPath evaluation failed, and fix that specific document/environment issue.
  2. Ensure the rule id contains only plain characters usable inside an XPath predicate (escape or avoid quotes/apostrophes).
  3. Verify the grammar XML files for the language parse correctly (validate with an XML tool).
  4. Ensure the runtime supports the DOM Level 3 Load/Save implementation (not a stripped JRE/GraalVM without it).

Example fix

// before
String xml = creator.toXML(new RuleId("it's-rule"), lang);
// after
String xml = creator.toXML(new RuleId("its-rule"), lang); // avoid quotes in rule ids
Defensive patterns

Strategy: try-catch

Validate before calling

// check id is XPath-predicate-safe
if (ruleId.getId().matches(".*['\[\]].*")) throw new IllegalArgumentException("Unsafe rule id: " + ruleId.getId());

Try / catch

try {
  xml = creator.toXML(ruleId, language);
} catch (RuntimeException e) {
  logger.warn("XML conversion failed for " + ruleId + ": " + e.getCause());
}

Prevention

When it happens

Trigger: Calling toXML(RuleId, Language) when XPath evaluation, document parsing (getDocument), or nodeToString throws for a rule whose id exists in filenames.

Common situations: 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.

Understand the failure class

Background: "JSON serialization failed", "not JSON serializable", "Failed to serialize": why JSON marshaling errors happen and how to fix them — this error's family across 46 libraries.

Related errors


AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06). Data as JSON: /api/errors/18ac35e8830f18a0. Report an issue: GitHub.