languagetool-org/languagetool · error · PathNotFoundException

Rule ' ' not found for language (LanguageTool version/date…

Error message

Rule '<ruleId>' not found for language <lang> (LanguageTool version/date: <VERSION>/<BUILD_DATE>, total rules of language: <rules.size>)

What it means

After building the rule set for the requested language, handleRuleExamplesRequest filters rules by id and, if none match, throws a PathNotFoundException naming the rule, the language, the LanguageTool version/build date, and the total rule count. This means the requested rule id simply does not exist for that language.

Solutions

  1. Verify the rule id exists for the given language via GET /v2/rules?lang=<lang> before requesting examples.
  2. Fix typos in the ruleId — ids are case-sensitive.
  3. If the rule is language-specific, request it with the correct 'lang' short code.
  4. If the rule disappeared after a LanguageTool upgrade, consult the version/date in the message and update your integration to the new rule id.

Example fix

// before
GET /v2/ruleExamples?lang=de-DE&ruleId=EN_A_VS_AN
// after
GET /v2/ruleExamples?lang=en-US&ruleId=EN_A_VS_AN
Defensive patterns

Strategy: try-catch

Validate before calling

const rules = await fetch(`${base}/v2/rules?lang=${lang}`).then(r => r.json());
if (!rules.rules.some(r => r.id === ruleId)) throw new Error(`Rule ${ruleId} does not exist for ${lang}`);

Try / catch

// HTTP 404 with body: { error: { message: "Rule 'X' not found for language Y ..." } }
try {
  const res = await fetch(examplesUrl);
  if (res.status === 404) {
    const body = await res.json();
    console.warn('Rule not found:', body.error?.message);
  } else {
    return res.json();
  }
} catch (e) { /* network error handling */ }

Prevention

When it happens

Trigger: GET /v2/ruleExamples?lang=de-DE&ruleId=EN_A_POSSESSIVE_ITS (an English-only rule asked for German); typo in the rule id; rule removed or renamed in a newer LanguageTool version.

Common situations: Hard-coded rule ids copied from another language; rules that only exist when specific grammar rules or ngram/language models are activated; clients not re-checking rule availability after a server upgrade.

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


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

Appendix: source

Thrown at languagetool-server/src/main/java/org/languagetool/server/ApiV2.java:285

      throw new BadRequestException("'lang' parameter missing");
    }
    if (params.get("ruleId") == null) {
      throw new BadRequestException("'ruleId' parameter missing");
    }
    Language lang = Languages.getLanguageForShortCode(params.get("lang"));
    JLanguageTool lt = new JLanguageTool(lang);
    if (textChecker.config.languageModelDir != null) {
      lt.activateLanguageModelRules(textChecker.config.languageModelDir);
    }
    List<Rule> rules = lt.getAllRules();
    List<Rule> foundRules = new ArrayList<>();
    for (Rule rule : rules) {
      if (rule.getId().equals(params.get("ruleId"))) {
        foundRules.add(rule);
      }
    }
    if (foundRules.isEmpty()) {
      throw new PathNotFoundException("Rule '" + params.get("ruleId") + "' not found for language " + lang +
              " (LanguageTool version/date: " + JLanguageTool.VERSION + "/" + JLanguageTool.BUILD_DATE + ", total rules of language: " + rules.size() + ")");
    }
    StringWriter sw = new StringWriter();
    try (JsonGenerator g = factory.createGenerator(sw)) {
      g.writeStartObject();
      g.writeArrayFieldStart("results");
      g.writeStartObject();
      g.writeStringField("warning", "*** This is not a public API - it may change anytime ***");
      g.writeEndObject();
      for (Rule foundRule : foundRules) {
        for (CorrectExample example : foundRule.getCorrectExamples()) {
          g.writeStartObject();
          g.writeStringField("status", "correct");
          g.writeStringField("sentence", example.getExample());
          g.writeEndObject();
        }
        for (IncorrectExample example : foundRule.getIncorrectExamples()) {
          g.writeStartObject();

View on GitHub (pinned to 2e990059ce)