languagetool-org/languagetool · error · IllegalArgumentException
ngramLangIdentData does not exist or is a directory (needs t
Error message
ngramLangIdentData does not exist or is a directory (needs to be a ZIP file):
What it means
The 'ngramLangIdentData' property must point to an existing ZIP file containing n-gram language-identification data. If the path does not exist or is a directory, HTTPServerConfig throws this IllegalArgumentException at startup.
Source
Thrown at languagetool-server/src/main/java/org/languagetool/server/HTTPServerConfig.java:516
String key = (String)o;
if (!KNOWN_OPTION_KEYS.contains(key) && !key.matches("lang-[a-z]+-dictPath") && !key.matches("lang-[a-z]+")) {
System.err.println("***** WARNING: ****");
System.err.println("Key '" + key + "' from configuration file '" + file + "' is unknown. Please check the key's spelling (case is significant).");
System.err.println("Known keys: " + KNOWN_OPTION_KEYS);
}
}
addDynamicLanguages(props);
setAbTest(getOptionalProperty(props, "abTest", null));
setAbTestClients(getOptionalProperty(props, "abTestClients", null));
setAbTestRollout(Integer.parseInt(getOptionalProperty(props, "abTestRollout", "100")));
String ngramLangIdentData = getOptionalProperty(props, "ngramLangIdentData", null);
setDefaultThirdPartyAI(Boolean.parseBoolean(getOptionalProperty(props, "defaultThirdPartyAI", "false")));
if (ngramLangIdentData != null) {
File dir = new File(ngramLangIdentData);
if (!dir.exists() || dir.isDirectory()) {
throw new IllegalArgumentException("ngramLangIdentData does not exist or is a directory (needs to be a ZIP file): " + ngramLangIdentData);
}
setNgramLangIdentData(dir);
}
}
} catch (IOException e) {
throw new RuntimeException("Could not load properties from '" + file + "'", e);
}
}
private void addDynamicLanguages(Properties props) throws IOException {
for (Object keyObj : props.keySet()) {
String key = (String)keyObj;
if (key.startsWith("lang-") && !key.contains("-dictPath")) {
String code = key.substring("lang-".length());
if (!code.contains("-") && code.length() != 2 && code.length() != 3) {
throw new IllegalArgumentException("code is supposed to be a 2 (or rarely 3) character code (unless it uses a format with variant, like xx-YY): '" + code + "'");
}
String nameKey = "lang-" + code;View on GitHub (pinned to 2e990059ce)
Solutions
- Point 'ngramLangIdentData' at the ZIP file itself (not the extracted directory)
- Download the ngram language-ident data package if it is missing
- Remove the 'ngramLangIdentData' property if this feature is not needed
Example fix
// before (server.properties) ngramLangIdentData=/opt/languagetool/ngrams/ // after (server.properties) ngramLangIdentData=/opt/languagetool/ngrams/langident.zip
Defensive patterns
Strategy: validation
Validate before calling
String p = props.getProperty("ngramLangIdentData");
if (p != null) {
File f = new File(p);
if (!f.exists() || f.isDirectory()) throw new IllegalStateException("ngramLangIdentData must be an existing ZIP file: " + p);
} Try / catch
try {
serverConfig = new HTTPServerConfig(props);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("ngramLangIdentData does not exist")) {
log.error("Point ngramLangIdentData at the ZIP file, not a directory: {}", e.getMessage());
}
throw e;
} Prevention
- Point the property at the .zip archive, never the extracted folder
- Verify with 'file <path>' that it is a zip before starting the server
- Remove the property if ngram language identification is not used
When it happens
Trigger: Server properties contains 'ngramLangIdentData=/path' where the path is missing, or points to a directory instead of the expected ZIP file (e.g. extracted archives).
Common situations: Operator downloaded and unzipped the language-ident data and pointed the config at the extracted folder; file not copied to the container; wrong filename.
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
- Rules Configuration file cannot be found:
- Remote rules configuration file cannot be found:
- beolingusFile not found:
- The AfterTheDeadline mode is not supported anymore in Langua
- Invalid value for cacheSize: , use 0 to deactivate cache
AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06).
Data as JSON: /api/errors/bee83339cdbfaa8e.
Report an issue: GitHub.