languagetool-org/languagetool · error · IllegalArgumentException

Use of cacheTTLSeconds without also setting cacheSize has no

Error message

Use of cacheTTLSeconds without also setting cacheSize has no effect.

What it means

Setting 'cacheTTLSeconds' only has an effect when the result cache is enabled via 'cacheSize'. To avoid a silently ineffective configuration, the server throws this IllegalArgumentException when cacheTTLSeconds is present but cacheSize is not set.

Source

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

        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"));
        suggestionsEnabled = Boolean.parseBoolean(getOptionalProperty(props, "suggestionsEnabled", "true"));
        maxSpellingSuggestions = Integer.parseInt(getOptionalProperty(props, "maxSpellingSuggestions", "0"));
        blockedReferrers = Arrays.asList(getOptionalProperty(props, "blockedReferrers", "").split(",\\s*"));
        setTrustedSources(getOptionalProperty(props, "trustedSources", null));
        String premiumAlwaysValue = props.getProperty("premiumAlways");
        if (premiumAlwaysValue != null) {
          premiumAlways = Boolean.parseBoolean(premiumAlwaysValue.trim());
          if (premiumAlways) {
            System.out.println("*** Running in PREMIUM-ALWAYS mode");
          }
        }
        premiumOnly = Boolean.valueOf(getOptionalProperty(props, "premiumOnly", "false").trim());
        if (premiumOnly) {
          if (!Premium.isPremiumVersion()) {
            throw new IllegalArgumentException("Cannot use premiumOnly=true with non-premium version");

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Add a 'cacheSize' property (e.g. cacheSize=1000) alongside cacheTTLSeconds to enable the cache
  2. Remove the 'cacheTTLSeconds' property if caching is not intended
  3. Both keys must appear together for a working cached setup

Example fix

// before (server.properties)
cacheTTLSeconds=300

// after (server.properties)
cacheSize=1000
cacheTTLSeconds=300
Defensive patterns

Strategy: validation

Validate before calling

if (props.containsKey("cacheTTLSeconds") && !props.containsKey("cacheSize")) {
    throw new IllegalStateException("cacheTTLSeconds requires cacheSize to be set");
}

Try / catch

try {
    serverConfig = new HTTPServerConfig(props);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("cacheTTLSeconds without also setting cacheSize")) {
        props.setProperty("cacheSize", "1000");
        serverConfig = new HTTPServerConfig(props);
    } else { throw e; }
}

Prevention

When it happens

Trigger: Server properties file contains 'cacheTTLSeconds=...' while 'cacheSize' is absent. Even with the default cacheSize of 0 (cache off), a TTL alone does nothing, so the config is rejected.

Common situations: Operator tunes cache expiry but forgets to enable/set cacheSize; docs examples showing only the TTL option; config files merged from different sources where cacheSize was dropped.

Related errors


AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06). Data as JSON: /api/errors/2ec4f90e4781c89c. Report an issue: GitHub.