languagetool-org/languagetool · error

Found more than one spell rule:

Error message

Found more than one spell rule: 

What it means

UnknownWordFinder.getSpellingCheckRule scans all active rules of a JLanguageTool instance and requires exactly one dictionary-based spelling rule. If a second one is found it throws a RuntimeException, since the tool needs a single unambiguous speller rule to configure.

Source

Thrown at languagetool-dev/src/main/java/org/languagetool/dev/UnknownWordFinder.java:64

  private final Set<String> unknownTag = new HashSet<>();

  private void run(File dir, JLanguageTool lt) throws IOException {
    SpellingCheckRule spellerRule = getSpellingCheckRule(lt);
    Tagger tagger = lt.getLanguage().getTagger();
    List<Path> files = Files.walk(dir.toPath()).filter(Files::isRegularFile).collect(Collectors.toList());
    for (Path file : files) {
      handle(file, lt, spellerRule, tagger);
    }
    printResult(unknownWords);
  }

  @NotNull
  private SpellingCheckRule getSpellingCheckRule(JLanguageTool lt) {
    SpellingCheckRule spellerRule = null;
    for (Rule rule : lt.getAllActiveRules()) {
      if (rule.isDictionaryBasedSpellingRule()) {
        if (spellerRule != null) {
          throw new RuntimeException("Found more than one spell rule: " + rule + ", " + spellerRule);
        }
        spellerRule = (SpellingCheckRule) rule;
      }
    }
    if (spellerRule == null) {
      throw new RuntimeException("No speller rule found for " + lt.getLanguage());
    }
    return spellerRule;
  }

  private void handle(Path f, JLanguageTool lt, SpellingCheckRule rule, Tagger tagger) throws IOException {
    String text = null;
    if (f.toString().toLowerCase().endsWith(".txt")) {
      List<String> lines = Files.readAllLines(f);
      text = String.join(" ", lines);
    } else if (f.toString().toLowerCase().endsWith(".rtf")) {
      text = getTextFromRtf(f);
    } else {

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Deactivate all but one dictionary-based spelling rule before passing the JLanguageTool to the finder (lt.disableRule(...) for the extras)
  2. Run the finder for a language that has a single active speller rule
  3. Patch the script to collect and use the first (or a chosen) speller rule instead of failing

Example fix

// before
SpellingCheckRule rule = getSpellingCheckRule(lt);
// after
lt.getAllActiveRules().stream().filter(Rule::isDictionaryBasedSpellingRule).skip(1).forEach(r -> lt.disableRule(r.getId()));
SpellingCheckRule rule = getSpellingCheckRule(lt);
Defensive patterns

Strategy: validation

Validate before calling

long n = lt.getAllActiveRules().stream().filter(Rule::isDictionaryBasedSpellingRule).count();
if (n != 1) throw new IllegalStateException("Expected exactly 1 spelling rule, got " + n);

Try / catch

try { new UnknownWordFinder(...).run(); } catch (RuntimeException e) { if (e.getMessage().startsWith("Found more than one spell rule")) { System.err.println("Disable extra spelling rules for this language"); } }

Prevention

When it happens

Trigger: Running UnknownWordFinder against a language whose configuration activates two or more dictionary-based spelling rules (e.g. both a hunspell and a simple spelling rule active).

Common situations: Languages with multiple spelling rules enabled by default; enabling extra spelling rules in custom configuration; recent rule additions changing the active-rule set.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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