languagetool-org/languagetool · error · RuntimeException

No grams directory found in

Error message

No ${ngramSize}grams directory found in ${topIndexDir}

What it means

getLuceneSearcher(ngramSize) looks up a pre-loaded LuceneSearcher for the requested ngram size in luceneSearcherMap. If no searcher was registered for that size (because no '<n>grams' directory exists under the top index directory), it throws. This typically means the index layout on disk does not match what the model was configured to load.

Solutions

  1. Download/use the full ngram index for the language that includes all needed '<n>grams' directories (1grams, 2grams, 3grams).
  2. Verify the top index directory contains subdirectories literally named '<n>grams' (e.g. '3grams', not '3-grams' or 'trigrams').
  3. Check extraction of the index archive completed (no truncated/missing subdirectories).
  4. Match the index release to your LanguageTool version; older indexes may have different layouts.

Example fix

// before: only 1grams/2grams present
$ ls /data/ngrams/en -> 1grams 2grams
// after: fetch full index
$ ls /data/ngrams/en -> 1grams 2grams 3grams
Defensive patterns

Strategy: validation

Validate before calling

for (int n : new int[]{1,2,3}) {
  File d = new File(topIndexDir, n + "grams");
  if (!d.isDirectory()) throw new IllegalStateException("Missing " + d);
}

Prevention

When it happens

Trigger: Calling getCount() (or anything resolving a searcher) with an ngram size whose '<n>grams' directory was not found or not registered when the model scanned topIndexDir; e.g. requesting trigram lookups when only 1grams/2grams directories exist.

Common situations: Downloading an index that ships only 1grams/2grams but running rules that need 3grams; mistyping/misplacing directories so names don't match the expected '<n>grams' pattern; incomplete archive extraction.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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

Appendix: source

Thrown at languagetool-core/src/main/java/org/languagetool/languagemodel/LuceneSingleIndexLanguageModel.java:173

        for (ScoreDoc scoreDoc : docs.scoreDocs) {
          long tmp = Long.parseLong(luceneSearcher.reader.document(scoreDoc.doc).get("totalTokenCount"));
          if (tmp > result) {
            // due to the way FrequencyIndexCreator adds these totalTokenCount fields, we must not sum them,
            // but take the largest one:
            result = tmp;
          }
        }
        return result;
      }
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  protected LuceneSearcher getLuceneSearcher(int ngramSize) {
    LuceneSearcher luceneSearcher = luceneSearcherMap.get(ngramSize);
    if (luceneSearcher == null) {
      throw new RuntimeException("No " + ngramSize + "grams directory found in " + topIndexDir);
    }
    return luceneSearcher;
  }

  private LuceneSearcher getCachedLuceneSearcher(File indexDir) {
    LuceneSearcher luceneSearcher = dirToSearcherMap.get(indexDir);
    if (luceneSearcher == null) {
      try {
        LuceneSearcher newSearcher = new LuceneSearcher(indexDir);
        dirToSearcherMap.put(indexDir, newSearcher);
        return newSearcher;
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
    } else {
      return luceneSearcher;
    }
  }

View on GitHub (pinned to 2e990059ce)