languagetool-org/languagetool · error

not found - make sure files are names *.old and *.new in mu

Error message

 not found - make sure files are names *.old and *.new in multi-file mode

What it means

RuleMatchDiffFinder's multi-file mode expects input files in *.old/*.new pairs that differ only in a two-character language-code placeholder (XX). When, after locating a matching .old file, the corresponding .new file does not exist in the same directory, main() throws this RuntimeException naming the expected .new path.

Source

Thrown at languagetool-dev/src/main/java/org/languagetool/dev/diff/RuleMatchDiffFinder.java:665

      if (args.length != 4) {
        printUsageAndExit();
      }
      System.out.println("Running in multi-file mode, replacing 'XX' in filenames with lang codes...");
      String file1 = args[0];
      String file3 = args[2];
      String date = args[3];
      File dir = new File(file1).getParentFile();
      String templateName = new File(file1).getName();
      int varPos = templateName.indexOf("XX");
      for (String file : dir.list()) {
        if (file.length() >= varPos + 1) {
          StringBuilder tempName = new StringBuilder(file).replace(varPos, varPos + 2, "XX");
          if (tempName.toString().equals(templateName)) {
            String langCode = file.substring(varPos, varPos + 2);
            String tempNameNew = file.replace(".old", ".new");
            File newFile = new File(dir, tempNameNew);
            if (!newFile.exists()) {
              throw new RuntimeException(tempNameNew + " not found - make sure files are names *.old and *.new in multi-file mode");
            }
            System.out.println("==== " + file + " =================================");
            File oldFile = new File(dir, file);
            String outputDir = file3.replace("XX", langCode);
            diffFinder.run(parser, oldFile, newFile, new File(outputDir), langCode, date);
          }
        }
      }
    } else {
      if (args.length != 5) {
        System.out.println("Usage: " + RuleMatchDiffFinder.class.getSimpleName() + " <matches1> <matches2> <resultDir> <langCode> <date>");
        System.out.println(" <matches1> and <matches2> are text outputs of different versions of org.languagetool.dev.dumpcheck.SentenceSourceChecker run on the same input");
        System.out.println("                           or JSON outputs from org.languagetool.dev.httpchecker.HttpApiSentenceChecker");
        System.exit(1);
      }
      File file1 = new File(args[0]);
      File file2 = new File(args[1]);
      File outputDir = new File(args[2]);

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Create or restore the missing .new file at the exact path printed in the message
  2. Ensure both files use the exact *.old and *.new suffixes in the same directory and share the name template with XX placeholders
  3. Re-run after renaming, e.g. mv mismatched.new.ext proper-name.new
  4. If single-language, use the two-file mode (oldFile newFile resultDir langCode date) instead of multi-file mode

Example fix

// before
mv results-de.old.txt results-de.new.txt   # wrong name template
// after
mv results-XX.old.txt results-XX.new.txt   # or exactly matching de.old/de.new pair
Defensive patterns

Strategy: validation

Validate before calling

File dir = new File(args[0]);
for (File f : dir.listFiles((d, n) -> n.endsWith(".old"))) {
  File newF = new File(dir, f.getName().replace(".old", ".new"));
  if (!newF.isFile()) throw new IllegalStateException("missing pair: " + newF);
}

Type guard

static boolean isCompleteOldNewPair(File oldFile) {
  return oldFile.isFile() && new File(oldFile.getParentFile(),
    oldFile.getName().replace(".old", ".new")).isFile();
}

Try / catch

try {
  diffFinderMain(args);
} catch (RuntimeException e) {
  if (e.getMessage().contains("*.old and *.new")) {
    System.err.println("fix file pair: " + e.getMessage());
  } else throw e;
}

Prevention

When it happens

Trigger: Running the diff finder in multi-file mode (directory of files whose names contain the 'XX' language placeholder) where a file 'foo.old' exists but 'foo.new' is missing, or the .new file was named differently (e.g. '.diff', wrong extension, different case).

Common situations: Forgot to copy/rename one side of a before/after diff pair; partial checkout or cleanup removed *.new files; files renamed so the '.old'/'.new' suffix convention broke.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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