{"record":{"id":"415ab6d772a85f77","repo":"languagetool-org/languagetool","slug":"rules-configuration-file-cannot-be-found","errorCode":null,"errorMessage":"Rules Configuration file cannot be found: ","messagePattern":"Rules Configuration file cannot be found: ","errorType":"console","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"languagetool-server/src/main/java/org/languagetool/server/HTTPServerConfig.java","lineNumber":384,"sourceCode":"        // default value 0 = use maxCheckThreads setting (for compatibility)\n        maxTextCheckerThreads = Integer.parseInt(getOptionalProperty(props, \"maxTextCheckerThreads\", \"0\"));\n        if (maxTextCheckerThreads < 0) {\n          throw new IllegalArgumentException(\"Invalid value for maxTextCheckerThreads, must be >= 1: \" + maxTextCheckerThreads);\n        }\n        textCheckerQueueSize = Integer.parseInt(getOptionalProperty(props, \"textCheckerQueueSize\", \"8\"));\n        if (textCheckerQueueSize < 0) {\n          throw new IllegalArgumentException(\"Invalid value for textCheckerQueueSize, must be >= 1: \" + textCheckerQueueSize);\n        }\n\n        boolean atdMode = getOptionalProperty(props, \"mode\", \"LanguageTool\").equalsIgnoreCase(\"AfterTheDeadline\");\n        if (atdMode) {\n          throw new IllegalArgumentException(\"The AfterTheDeadline mode is not supported anymore in LanguageTool 3.8 or later\");\n        }\n        String rulesConfigFilePath = getOptionalProperty(props, \"rulesFile\", null);\n        if (rulesConfigFilePath != null) {\n          rulesConfigFile = new File(rulesConfigFilePath);\n          if (!rulesConfigFile.exists() || !rulesConfigFile.isFile()) {\n            throw new RuntimeException(\"Rules Configuration file cannot be found: \" + rulesConfigFile);\n          }\n        }\n        String remoteRulesConfigFilePath = getOptionalProperty(props, \"remoteRulesFile\", null);\n        if (remoteRulesConfigFilePath != null) {\n          remoteRulesConfigFile = new File(remoteRulesConfigFilePath);\n          if (!remoteRulesConfigFile.exists() || !remoteRulesConfigFile.isFile()) {\n            throw new RuntimeException(\"Remote rules configuration file cannot be found: \" + remoteRulesConfigFile);\n          }\n        }\n        cacheSize = Integer.parseInt(getOptionalProperty(props, \"cacheSize\", \"0\"));\n        if (cacheSize < 0) {\n          throw new IllegalArgumentException(\"Invalid value for cacheSize: \" + cacheSize + \", use 0 to deactivate cache\");\n        }\n        if (props.containsKey(\"cacheTTLSeconds\") && !props.containsKey(\"cacheSize\")) {\n          throw new IllegalArgumentException(\"Use of cacheTTLSeconds without also setting cacheSize has no effect.\");\n        }\n        cacheTTLSeconds = Integer.parseInt(getOptionalProperty(props, \"cacheTTLSeconds\", \"300\"));\n        maxErrorsPerWordRate = Float.parseFloat(getOptionalProperty(props, \"maxErrorsPerWordRate\", \"0\"));","sourceCodeStart":366,"sourceCodeEnd":402,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-server/src/main/java/org/languagetool/server/HTTPServerConfig.java#L366-L402","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Fix the 'rulesFile' property to an absolute path pointing to an existing regular file","Verify with 'ls -l <path>' that the file exists and is not a directory (or a dangling symlink)","If running in Docker, mount the file as a volume and use the in-container path","If no custom rules config is needed, remove the 'rulesFile' property entirely"],"exampleFix":"// before (server.properties)\nrulesFile=./config/rule-config.txt\n\n// after (server.properties)\nrulesFile=/opt/languagetool/config/rule-config.txt","handlingStrategy":"validation","validationCode":"String p = props.getProperty(\"rulesFile\");\nif (p != null) {\n    File f = new File(p);\n    if (!f.exists() || !f.isFile()) throw new IllegalStateException(\"rulesFile missing or not a file: \" + p);\n}","typeGuard":null,"tryCatchPattern":"try {\n    serverConfig = new HTTPServerConfig(props);\n} catch (RuntimeException e) {\n    if (e.getMessage().startsWith(\"Rules Configuration file cannot be found\")) {\n        log.error(\"Fix the rulesFile path: {}\", e.getMessage());\n    }\n    throw e;\n}","preventionTips":["Use absolute paths in server.properties","Mount config files into containers explicitly and verify with a startup existence check","Deploy the rules file before starting the server (provisioning order)"],"tags":["java","languagetool","file-not-found","server-config"],"backgroundTag":"file-not-found","analyzedSha":"2e990059ce67d5e2a0f7f7ca5d31160c6709df4b","analyzedAt":"2026-09-06T09:20:17.015Z","contentChangedAt":"2026-09-06T09:20:17.015Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}