languagetool-org/languagetool · error · RuntimeException

Rules Configuration file cannot be found:

Error message

Rules Configuration file cannot be found: 

What it means

The 'rulesFile' server property points to a rules configuration file that customizes rule behavior. If the path given does not exist on disk or is not a regular file (e.g. a directory), the server config constructor throws this RuntimeException because it cannot apply the requested rules configuration.

Source

Thrown at languagetool-server/src/main/java/org/languagetool/server/HTTPServerConfig.java:384

        // default value 0 = use maxCheckThreads setting (for compatibility)
        maxTextCheckerThreads = Integer.parseInt(getOptionalProperty(props, "maxTextCheckerThreads", "0"));
        if (maxTextCheckerThreads < 0) {
          throw new IllegalArgumentException("Invalid value for maxTextCheckerThreads, must be >= 1: " + maxTextCheckerThreads);
        }
        textCheckerQueueSize = Integer.parseInt(getOptionalProperty(props, "textCheckerQueueSize", "8"));
        if (textCheckerQueueSize < 0) {
          throw new IllegalArgumentException("Invalid value for textCheckerQueueSize, must be >= 1: " + textCheckerQueueSize);
        }

        boolean atdMode = getOptionalProperty(props, "mode", "LanguageTool").equalsIgnoreCase("AfterTheDeadline");
        if (atdMode) {
          throw new IllegalArgumentException("The AfterTheDeadline mode is not supported anymore in LanguageTool 3.8 or later");
        }
        String rulesConfigFilePath = getOptionalProperty(props, "rulesFile", null);
        if (rulesConfigFilePath != null) {
          rulesConfigFile = new File(rulesConfigFilePath);
          if (!rulesConfigFile.exists() || !rulesConfigFile.isFile()) {
            throw new RuntimeException("Rules Configuration file cannot be found: " + rulesConfigFile);
          }
        }
        String remoteRulesConfigFilePath = getOptionalProperty(props, "remoteRulesFile", null);
        if (remoteRulesConfigFilePath != null) {
          remoteRulesConfigFile = new File(remoteRulesConfigFilePath);
          if (!remoteRulesConfigFile.exists() || !remoteRulesConfigFile.isFile()) {
            throw new RuntimeException("Remote rules configuration file cannot be found: " + remoteRulesConfigFile);
          }
        }
        cacheSize = Integer.parseInt(getOptionalProperty(props, "cacheSize", "0"));
        if (cacheSize < 0) {
          throw new IllegalArgumentException("Invalid value for cacheSize: " + cacheSize + ", use 0 to deactivate cache");
        }
        if (props.containsKey("cacheTTLSeconds") && !props.containsKey("cacheSize")) {
          throw new IllegalArgumentException("Use of cacheTTLSeconds without also setting cacheSize has no effect.");
        }
        cacheTTLSeconds = Integer.parseInt(getOptionalProperty(props, "cacheTTLSeconds", "300"));
        maxErrorsPerWordRate = Float.parseFloat(getOptionalProperty(props, "maxErrorsPerWordRate", "0"));

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Fix the 'rulesFile' property to an absolute path pointing to an existing regular file
  2. Verify with 'ls -l <path>' that the file exists and is not a directory (or a dangling symlink)
  3. If running in Docker, mount the file as a volume and use the in-container path
  4. If no custom rules config is needed, remove the 'rulesFile' property entirely

Example fix

// before (server.properties)
rulesFile=./config/rule-config.txt

// after (server.properties)
rulesFile=/opt/languagetool/config/rule-config.txt
Defensive patterns

Strategy: validation

Validate before calling

String p = props.getProperty("rulesFile");
if (p != null) {
    File f = new File(p);
    if (!f.exists() || !f.isFile()) throw new IllegalStateException("rulesFile missing or not a file: " + p);
}

Try / catch

try {
    serverConfig = new HTTPServerConfig(props);
} catch (RuntimeException e) {
    if (e.getMessage().startsWith("Rules Configuration file cannot be found")) {
        log.error("Fix the rulesFile path: {}", e.getMessage());
    }
    throw e;
}

Prevention

When it happens

Trigger: Starting the HTTP server with 'rulesFile=/path/to/file' where the path does not exist, is a directory, or the server's working directory/container differs from where the file was placed.

Common situations: Relative path in server.properties resolved against a different working directory when started via systemd/Docker; file deleted or renamed; typo in path; Docker volume not mounted.

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/415ab6d772a85f77. Report an issue: GitHub.