languagetool-org/languagetool · error · IOException

Invalid line format (DE item count != EN item count): " + li

Error message

Invalid line format (DE item count != EN item count): " + line

What it means

BeoLingusTranslator loads a tab/separator-delimited bilingual dictionary file where each line is 'german :: english', and the '|' character separates alternative items on each side. When parsing a line, if the German side and English side contain a different number of '|' separated items, the parallel translation mapping cannot be built and an IOException is thrown naming the offending line.

Source

Thrown at languagetool-language-modules/en/src/main/java/org/languagetool/rules/en/translation/BeoLingusTranslator.java:94

      logger.info("Init dict done (" + (t2-t1) + "ms) - loaded " + instance.getDeEnSize() + " de -> en items.");
    }
    return instance;
  }

  public BeoLingusTranslator(File file) throws IOException {
    tagger = Languages.getLanguageForShortCode("de").getTagger();
    List<String> lines = Files.readAllLines(file.toPath());
    for (String line : lines) {
      if (line.trim().isEmpty() || line.startsWith("#")) {
        continue;
      }
      String[] parts = line.split(" :: ");
      String german = parts[0];
      String english = parts[1];
      String[] germanParts = german.split("\\|");
      String[] englishParts = english.split("\\|");
      if (germanParts.length != englishParts.length) {
        throw new IOException("Invalid line format (DE item count != EN item count): " + line);
      }
      int i = 0;
      for (String germanPart : germanParts) {
        handleItem(de2en, germanParts, englishParts, i, germanPart);
        //handleItem(en2de, englishParts, germanParts, i, englishParts[i]);  -- direction not supported yet
        i++;
      }
    }
  }

  private void handleItem(Map<String, List<TranslationEntry>> map, String[] germanParts, String[] englishParts, int i, String germanPart) {
    germanPart = germanPart.replaceAll("/.*?/", "");    // e.g. "oder {conj} /o.; od./"
    List<String> germanSubParts = split(germanPart);
    for (String germanSubPart : germanSubParts) {
      String key = cleanForLookup(germanSubPart);
      List<TranslationEntry> oldEntries = map.get(key);
      if (oldEntries != null) {
        if (!englishParts[i].trim().isEmpty()) {

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Open the dictionary file, find the reported line, and make the '|' item counts equal on both sides of ' :: '.
  2. Remove extra '|' separators if they are not intended as parallel item delimiters.
  3. Replace the dictionary resource with a known-good version of the BeoLingus data file.

Example fix

// before (dictionary line)
Haus|Gebäude :: house
// after
Haus|Gebäude :: house|building
Defensive patterns

Strategy: try-catch

Validate before calling

String[] de = line.split(" :: ")[0].split("\\|");
String[] en = line.split(" :: ")[1].split("\\|");
if (de.length != en.length) throw new IllegalArgumentException("Mismatched items: " + line);

Try / catch

try (var reader = ...) { /* load dictionary */ } catch (IOException e) {
  if (e.getMessage().startsWith("Invalid line format")) { /* fix data file or skip line */ }
}

Prevention

When it happens

Trigger: Calling the BeoLingusTranslator constructor on a dictionary resource file that contains a line where split("|") on the German part yields a different count than on the English part, e.g. 'Haus :: house|building'.

Common situations: A corrupted or hand-edited BeoLingus dump; an updated dictionary file with a format drift; adding a synonym on one language side only; wrong file loaded into the translator.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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