languagetool-org/languagetool · error

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

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.

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.

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