{"record":{"id":"821b67ed6bcb9cfb","repo":"languagetool-org/languagetool","slug":"no-directories-1grams-3grams-found-in-to","errorCode":null,"errorMessage":"No directories '1grams' ... '3grams' found in ${topIndexDir}","messagePattern":"No directories '1grams' \\.\\.\\. '3grams' found in (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"languagetool-core/src/main/java/org/languagetool/languagemodel/LuceneSingleIndexLanguageModel.java","lineNumber":98,"sourceCode":"  @Experimental\n  public static void clearCaches() {\n    dirToSearcherMap.clear();\n  }\n\n  /**\n   * @param topIndexDir a directory which contains at least another sub directory called {@code 3grams},\n   *                    which is a Lucene index with ngram occurrences as created by\n   *                    {@code org.languagetool.dev.FrequencyIndexCreator}.\n   */\n  public LuceneSingleIndexLanguageModel(File topIndexDir)  {\n    doValidateDirectory(topIndexDir);\n    this.topIndexDir = topIndexDir;\n    addIndex(topIndexDir, 1);\n    addIndex(topIndexDir, 2);\n    addIndex(topIndexDir, 3);\n    addIndex(topIndexDir, 4);\n    if (luceneSearcherMap.isEmpty()) {\n      throw new RuntimeException(\"No directories '1grams' ... '3grams' found in \" + topIndexDir);\n    }\n    maxNgram = Collections.<Integer>max(luceneSearcherMap.keySet());\n  }\n\n  public LuceneSingleIndexLanguageModel(int maxNgram) {\n    this.maxNgram = maxNgram;\n    this.topIndexDir = null;\n  }\n\n  protected void doValidateDirectory(File topIndexDir) {\n    validateDirectory(topIndexDir);\n  }\n\n  private void addIndex(File topIndexDir, int ngramSize) {\n    File indexDir = new File(topIndexDir, ngramSize + \"grams\");\n    if (indexDir.exists() && indexDir.isDirectory()) {\n      if (luceneSearcherMap.containsKey(ngramSize)) {\n        throw new RuntimeException(\"Searcher for ngram size \" + ngramSize + \" already exists\");","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-core/src/main/java/org/languagetool/languagemodel/LuceneSingleIndexLanguageModel.java#L80-L116","documentation":"After adding indexes for ngram sizes 1-4, the LuceneSingleIndexLanguageModel constructor checks whether any searcher was actually registered. If luceneSearcherMap is empty — no *grams directory existed — it throws RuntimeException.","triggerScenarios":"Instantiating LuceneSingleIndexLanguageModel(File topIndexDir) where topIndexDir exists but contains no 1grams/2grams/3grams/4grams directories (e.g. without the validateDirectory path having rejected it first).","commonSituations":"Same wrong-path problems as the validation errors: empty directory, data not yet extracted, path typo; differs from [34]/[35] only in the constructor variant used.","solutions":["Point the constructor at the directory containing the extracted 1grams...3grams subdirectories","Extract the ngram data archive to the configured location","Verify with ls that *grams directories exist before constructing"],"exampleFix":"// before\nnew LuceneSingleIndexLanguageModel(new File(\"/data/empty\"));\n// after\nnew LuceneSingleIndexLanguageModel(new File(\"/data/en\")); // has 1grams..3grams","handlingStrategy":"validation","validationCode":"if (ngramDir == null || !ngramDir.isDirectory()) throw new IllegalStateException(\"Not a directory: \" + ngramDir);\nboolean any = Arrays.stream(ngramDir.list()).anyMatch(n -> n.matches(\"[1-4]grams\"));\nif (!any) throw new IllegalStateException(\"No ngram subdirectories in \" + ngramDir);","typeGuard":null,"tryCatchPattern":"try { model = new LuceneSingleIndexLanguageModel(ngramDir); } catch (RuntimeException e) { if (e.getMessage().startsWith(\"No directories\")) { /* point to correct index dir */ } throw e; }","preventionTips":["Ensure the ngram data archive is extracted before service startup","Log the resolved absolute index path on startup for easy debugging","Fail fast at boot with a directory check rather than lazily on first use"],"tags":["java","lucene","ngrams","missing-data"],"backgroundTag":"directory-not-found","analyzedSha":"2e990059ce67d5e2a0f7f7ca5d31160c6709df4b","analyzedAt":"2026-09-06T09:20:17.015Z","contentChangedAt":"2026-09-06T09:20:17.015Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}