languagetool-org/languagetool · error · IllegalArgumentException

<dir.getAbsolutePath()> is not a directory, cannot use recur

Error message

<dir.getAbsolutePath()> is not a directory, cannot use recursion

What it means

Main.runRecursive recurses into a directory to process every file. File.listFiles() returns null when the path is not a directory (or is unreadable), and the method converts that into IllegalArgumentException '<path> is not a directory, cannot use recursion'. This is the recursion-mode (-r/--recursive) guard.

Source

Thrown at languagetool-commandline/src/main/java/org/languagetool/commandline/Main.java:315

        ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_16LE,
        ByteOrderMark.UTF_32BE,ByteOrderMark.UTF_32LE);
      if (bomIn.hasBOM() && encoding == null) {
        charsetName = bomIn.getBOMCharsetName();
      }
      is = bomIn;
    }
    return new InputStreamReader(new BufferedInputStream(is), charsetName);
  }

  private boolean isStdIn(String filename) {
    return "-".equals(filename);
  }

  private void runRecursive(String filename, String encoding, boolean xmlFiltering, JLanguageTool.Level level) {
    File dir = new File(filename);
    File[] files = dir.listFiles();
    if (files == null) {
      throw new IllegalArgumentException(dir.getAbsolutePath() + " is not a directory, cannot use recursion");
    }
    for (File file : files) {
      try {
        if (file.isDirectory()) {
          runRecursive(file.getAbsolutePath(), encoding, xmlFiltering, level);
        } else {
          if (options.isLineByLine()) {
            runOnFileLineByLine(file.getAbsolutePath(), encoding, level);
          } else {
            runOnFile(file.getAbsolutePath(), encoding, xmlFiltering);
          }
        }
      } catch (Exception e) {
        throw new RuntimeException("Could not check text in file " + file, e);
      }
    }    
  }

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Pass a directory (not a file) when using -r/--recursive
  2. Verify the path exists and is readable before running (e.g. `[ -d "$DIR" ]` or File.isDirectory())
  3. Drop -r for single-file input
  4. Fix filesystem permissions if the directory cannot be read

Example fix

// before
ltMain.runRecursive("notes.txt", "utf-8", false, null);
// after
File dir = new File("notes/");
if (dir.isDirectory()) {
  ltMain.runRecursive(dir.getAbsolutePath(), "utf-8", false, null);
}
Defensive patterns

Strategy: validation

Validate before calling

File dir = new File(path);
if (!dir.isDirectory()) {
  throw new IllegalArgumentException(path + " must be an existing, readable directory when using --recursive");
}

Type guard

static boolean isReadableDirectory(String path) {
  File d = new File(path);
  return d.isDirectory() && d.canRead();
}

Try / catch

try {
  runRecursive(path, encoding, xmlFiltering, level);
} catch (IllegalArgumentException e) {
  if (e.getMessage().endsWith("is not a directory, cannot use recursion")) {
    System.err.println("--recursive requires a directory; got: " + path);
    System.exit(2);
  }
  throw e;
}

Prevention

When it happens

Trigger: Passing -r/--recursive together with a plain file (or a nonexistent path) instead of a directory, e.g. `languagetool -r -l en file.txt`; also directories the process cannot read cause listFiles() to return null and the same error.

Common situations: Enabling recursion in a script that sometimes receives single files; path typos so the directory does not exist; permission problems on the directory.

Related errors


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