languagetool-org/languagetool · error · RuntimeException

The 'ruleIdToConfidenceFile' parameter must contain '{lang}'

Error message

The 'ruleIdToConfidenceFile' parameter must contain '{lang}' as a placeholder for the language code

What it means

ConfidenceMapLoader.load expects a file path pattern containing the literal '{lang}' placeholder, which is substituted per language short code when loading rule confidence mappings. A pattern without '{lang}' cannot be expanded per language and throws RuntimeException at startup.

Source

Thrown at languagetool-server/src/main/java/org/languagetool/server/ConfidenceMapLoader.java:43

import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static java.nio.charset.StandardCharsets.UTF_8;

class ConfidenceMapLoader {

  private static final Logger logger = LoggerFactory.getLogger(ConfidenceMapLoader.class);

  Map<ConfidenceKey,Float> load(File filePattern) throws IOException {
    if (!filePattern.toString().contains("{lang}")) {
      throw new RuntimeException("The 'ruleIdToConfidenceFile' parameter must contain '{lang}' as a placeholder for the language code");
    }
    Map<ConfidenceKey,Float> confMap = new HashMap<>();
    for (Language lang : Languages.get()) {
      int loadCount = 0;
      String fileName = filePattern.getAbsolutePath().replace("{lang}", lang.getShortCode());
      if (!Paths.get(fileName).toFile().exists()) {
        continue;
      }
      List<String> lines = Files.readAllLines(Paths.get(fileName), UTF_8);
      for (String line : lines) {
        if (line.startsWith("#")) {
          continue;
        }
        String[] parts = line.split(",");
        if (parts.length >= 2) {   // there might be more columns for better debugging, but we don't use them here
          try {
            float confidence = Float.parseFloat(parts[1]);
            confMap.put(new ConfidenceKey(lang, parts[0]), confidence);

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Add '{lang}' to the configured file path, e.g. /path/confidence-{lang}.csv.
  2. Create per-language files matching the pattern (confidence-en.csv, confidence-de.csv, ...).
  3. Restart the server after fixing the config value.

Example fix

// before
ruleIdToConfidenceFile=/etc/languagetool/confidence.csv
// after
ruleIdToConfidenceFile=/etc/languagetool/confidence-{lang}.csv
Defensive patterns

Strategy: validation

Validate before calling

if (!confidenceFilePattern.includes('{lang}')) {
  throw new Error("ruleIdToConfidenceFile must contain '{lang}'");
}

Type guard

function isValidLangPattern(p) { return typeof p === 'string' && p.includes('{lang}'); }

Try / catch

try {
  Map<ConfidenceKey,Float> map = new ConfidenceMapLoader().load(filePattern);
} catch (RuntimeException e) {
  logger.error("Bad confidence file pattern: " + e.getMessage());
}

Prevention

When it happens

Trigger: Starting languagetool-server with the 'ruleIdToConfidenceFile' config parameter set to a plain path like /conf/confidence.csv instead of /conf/confidence-{lang}.csv.

Common situations: Copying a single-language confidence file config into a multi-language deployment; misreading the parameter name as a plain file path.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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