{"record":{"id":"688ac76d5e1dc110","repo":"languagetool-org/languagetool","slug":"directory-must-contain-at-least-1grams-2grams","errorCode":null,"errorMessage":"Directory must contain at least '1grams', '2grams', and '3grams': ${topIndexDir.getAbsolutePath()}","messagePattern":"Directory must contain at least '1grams', '2grams', and '3grams': (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"languagetool-core/src/main/java/org/languagetool/languagemodel/LuceneSingleIndexLanguageModel.java","lineNumber":69,"sourceCode":"   * Throw RuntimeException is the given directory does not seem to be a valid ngram top directory\n   * with sub directories {@code 1grams} etc.\n   * @since 3.0\n   */\n  public static void validateDirectory(File topIndexDir) {\n    if (!topIndexDir.exists() || !topIndexDir.isDirectory()) {\n      throw new RuntimeException(\"Not found or is not a directory:\\n\" +\n              topIndexDir + \"\\n\" +\n              \"As ngram directory, please select the directory that has a subdirectory like 'en'\\n\" +\n              \"(or whatever language code you're using).\");\n    }\n    List<String> dirs = new ArrayList<>();\n    for (String name : topIndexDir.list()) {\n      if (name.matches(\"[123]grams\")) {\n        dirs.add(name);\n      }\n    }\n    if (dirs.isEmpty()) {\n      throw new RuntimeException(\"Directory must contain at least '1grams', '2grams', and '3grams': \" + topIndexDir.getAbsolutePath());\n    }\n    if (dirs.size() < 3) {\n      throw new RuntimeException(\"Expected at least '1grams', '2grams', and '3grams' sub directories but only got \" + dirs + \" in \" + topIndexDir.getAbsolutePath());\n    }\n  }\n  \n  /**\n   * Only used internally. \n   * @since 3.2 \n   */\n  @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","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-core/src/main/java/org/languagetool/languagemodel/LuceneSingleIndexLanguageModel.java#L51-L87","documentation":"LuceneSingleIndexLanguageModel validates that the ngram index directory contains subdirectories named '1grams', '2grams', '3grams'. If the top directory contains none of these, validateDirectory throws RuntimeException naming the path.","triggerScenarios":"Constructing a LuceneSingleIndexLanguageModel (which calls doValidateDirectory) pointing at a directory that contains no ngram subdirectories at all — empty dir, wrong dir, or an index not yet unpacked.","commonSituations":"Pointing the ngram data path at the parent directory of the index, a typo in the configured path, or the ngram archive extracted to a nested folder so the *grams dirs aren't at the top level.","solutions":["Verify the path points to the directory directly containing 1grams/, 2grams/, 3grams/","Fix the configuration so it references the extracted ngram index directory","Download/extract the correct language ngram index from LanguageTool"],"exampleFix":"// before\nLanguageModel lm = new LuceneSingleIndexLanguageModel(new File(\"/data\")); // /data lacks *grams\n// after\nLanguageModel lm = new LuceneSingleIndexLanguageModel(new File(\"/data/en/ngrams\")); // contains 1grams..3grams","handlingStrategy":"validation","validationCode":"File[] subs = ngramDir.listFiles(File::isDirectory);\nSet<String> names = Arrays.stream(subs).map(File::getName).collect(Collectors.toSet());\nif (!names.containsAll(Set.of(\"1grams\",\"2grams\",\"3grams\"))) throw new IllegalStateException(\"Ngram index incomplete: \" + ngramDir);","typeGuard":null,"tryCatchPattern":"try { model = new LuceneSingleIndexLanguageModel(ngramDir); } catch (RuntimeException e) { if (e.getMessage().contains(\"grams\")) { /* fix path or re-extract data */ } throw e; }","preventionTips":["Verify the directory contains 1grams/, 2grams/, 3grams/ at startup, before use","Extract the official ngram archive fully and point config at the exact extraction dir","Add a health check that constructs the model early so bad paths fail fast"],"tags":["java","lucene","ngrams","file-layout"],"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"}