languagetool-org/languagetool · error · RuntimeException

IOException during dictionary list loading

Error message

IOException during dictionary list loading

What it means

ExtraDictionaryLoader.loadLists() reads dictionary lists from an InputStream and wraps any IOException in an unchecked RuntimeException. This is a fail-fast pattern: the dictionary data is required for the rule to work, so the library aborts instead of silently returning partial data. The exception message is generic because the original IOException is used only as the cause.

Source

Thrown at languagetool-language-modules/uk/src/main/java/org/languagetool/rules/uk/ExtraDictionaryLoader.java:68

    }
    return result;
  }

  public static Map<String, List<String>> loadLists(String path) {
    Map<String, List<String>> result = new HashMap<>();
    try (InputStream is = JLanguageTool.getDataBroker().getFromRulesDirAsStream(path);
         Scanner scanner = new Scanner(is, "UTF-8")) {
      while (scanner.hasNextLine()) {
        String line = scanner.nextLine();
        if( ! line.startsWith("#") && ! line.trim().isEmpty() ) {
          String[] split = line.split(" *= *|\\|");
          List<String> list = Arrays.asList(split).subList(1, split.length);
          result.put(split[0], list);
        }
      }
      return result;
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

}

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Check network connectivity and make the source URL reachable (curl it from the same host).
  2. Verify any proxy settings (-Dhttps.proxyHost/-Dhttps.proxyPort) and truststore configuration for HTTPS sources.
  3. Inspect the cause chain (e.getCause()) to see the underlying IOException and address it specifically.
  4. Cache the dictionary list locally and load from a local file/stream instead of the network.
  5. If the list is no longer hosted, update the URL in the source to the new location.

Example fix

// before
try {
  return loadLists(stream);
} catch (IOException e) {
  throw new RuntimeException(e);
}
// after
try {
  return loadLists(stream);
} catch (IOException e) {
  throw new RuntimeException("Failed to load extra dictionary lists from " + sourceUrl, e);
}
Defensive patterns

Strategy: try-catch

Validate before calling

URL url = new URL(sourceUrl);
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setConnectTimeout(5000);
if (c.getResponseCode() != 200) throw new IllegalStateException("List source unreachable: " + c.getResponseCode());

Try / catch

try { result = loader.loadLists(stream); }
catch (RuntimeException e) {
  Throwable cause = e.getCause();
  if (cause instanceof IOException) { LOG.error("Dictionary list I/O failure", cause); /* fallback to cached list */ }
  else throw e;
}

Prevention

When it happens

Trigger: Calling loadLists() when the underlying data source (URL or stream) is unreachable, returns an error, or the connection drops mid-read while splitting lines into key/value lists.

Common situations: No network access or offline environment when loading remote dictionaries; the remote Wikipedia-derived list host is down or rate-limiting; a proxy/firewall blocks the request; TLS failures in restricted JVMs.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


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