languagetool-org/languagetool · error · IOException

Could not load remote rules.

Error message

Could not load remote rules.

What it means

activateRemoteRules(List) variant that loads configs from a file wraps loading failures in an IOException 'Could not load remote rules.' This fires when RemoteRuleConfig.load(configFile) itself throws IOException while reading/parsing the remote-rule configuration file.

Source

Thrown at languagetool-core/src/main/java/org/languagetool/JLanguageTool.java:645

      Rule original = rules.get(i);
      Rule transformed = mapper.apply(original);
      if (transformed != original) {
        rules.set(i, transformed);
      }
    }
  }

  public void activateRemoteRules(@Nullable File configFile) throws IOException {
    List<RemoteRuleConfig> configs;
    try {
      if (configFile != null) {
        configs = RemoteRuleConfig.load(configFile);
      } else {
        configs = Collections.emptyList();
      }
      activateRemoteRules(configs);
    } catch (IOException e) {
      throw new IOException("Could not load remote rules.", e);
    } catch (ExecutionException e) {
      throw new IOException("Could not load remote rules configuration at " + configFile.getAbsolutePath(), e);
    }
  }

  public void activateRemoteRules(List<RemoteRuleConfig> configs) throws IOException {
    // Apply A/B test filtering first - can affect which rules get enabled and thus disabled because of fallback settings
    List<String> activeAbTestsForUser = userConfig.getAbTest();
    List<RemoteRuleConfig> selectedConfigsByUserSettings = configs.stream()
      .filter(config -> {
        if (!userConfig.isPremium() && config.isPremium()) {
          return false;
        }
        String excludeABTest = config.getOptions().get("excludeABTest");
        if (excludeABTest != null && activeAbTestsForUser != null &&
          activeAbTestsForUser.stream().anyMatch(flag -> flag.matches(excludeABTest))) {
          return false;
        }

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Confirm the config file path exists and is readable by the process.
  2. Validate the remote-rule configuration file's syntax against RemoteRuleConfig's expected format.
  3. If no remote rules are wanted, pass an empty config / don't call the file-based overload (use the List overload).
  4. Check the 'Caused by' IOException for the precise file or parsing problem.

Example fix

// before
lt.activateRemoteRules(new File(System.getenv("REMOTE_RULES"))); // env unset -> null path
// after
String path = System.getenv("REMOTE_RULES");
if (path != null && new File(path).isFile()) { lt.activateRemoteRules(new File(path)); }
Defensive patterns

Strategy: validation

Validate before calling

File cfg = new File(path);
if (!cfg.isFile() || !cfg.canRead()) {
  throw new IllegalArgumentException("remote rules config not readable: " + path);
}

Try / catch

try {
  lt.activateRemoteRules(configFile);
} catch (IOException e) {
  if (e.getMessage().startsWith("Could not load remote rules")) {
    logger.error("Remote rules config unreadable: " + e.getCause());
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling activateRemoteRules(File configFile) (or API paths testAbFlags/testThirdPartyAI* that use it) when the config file is missing, unreadable, or has invalid remote-rule configuration content causing RemoteRuleConfig.load to throw IOException.

Common situations: Server deployments pointing remoteRuleConfig at a nonexistent path; malformed YAML/properties in the remote rules config; permission changes after deployment; tests enabling remote rules without a config file.

Understand the failure class

Background: "Config file not found": what it means and how to fix it in docker-sync, Maven, Vagrant, Turborepo and other tools — this error's family across 60 libraries.

Related errors


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