languagetool-org/languagetool · error · IOException

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

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.

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.

Appendix: 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)