languagetool-org/languagetool · error · IllegalArgumentException

Profiling mode cannot be used with input from STDIN

Error message

Profiling mode cannot be used with input from STDIN

What it means

Main.runOnFileLineByLine processes input line by line and supports STDIN, but profiling mode (-p/--profile) needs to re-run the whole input repeatedly against all rules, which is impossible with a stream. When profileRules is true and isStdIn(filename) is true it throws IllegalArgumentException 'Profiling mode cannot be used with input from STDIN'.

Source

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

        System.out.println("Unknown words: " + lt.getUnknownWords());
      }
    }
  }

  private void runOnFileLineByLine(String filename, String encoding, JLanguageTool.Level level) throws IOException {
    System.err.println("Warning: running in line by line mode. Cross-paragraph checks will not work.\n");
    if (options.isVerbose()) {
      lt.setOutput(System.err);
    }
    if (!options.isApplySuggestions()) {
      if (isStdIn(filename)) {
        System.err.println("Working on STDIN...");
      } else {
        System.err.println("Working on " + filename + "...");
      }
    }
    if (profileRules && isStdIn(filename)) {
      throw new IllegalArgumentException("Profiling mode cannot be used with input from STDIN");
    }
    int runCount = 1;
    List<Rule> rules = lt.getAllActiveRules();
    if (profileRules) {
      System.out.printf("Testing %d rules\n", rules.size());
      System.out.println("Rule ID\tTime\tSentences\tMatches\tSentences per sec.");
      runCount = rules.size();
    }
    int lineOffset = 0;
    int tmpLineOffset = 0;
    handleLine(ApiPrintMode.START_API, 0, new StringBuilder(), level);
    StringBuilder sb = new StringBuilder();
    for (int ruleIndex = 0; !rules.isEmpty() && ruleIndex < runCount; ruleIndex++) {
      currentRule = rules.get(ruleIndex);
      try (
          InputStreamReader isr = getInputStreamReader(filename, encoding);
          BufferedReader br = new BufferedReader(isr)
      ) {

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Pass a real file path on the command line when using -p/--profile
  2. Remove the -p flag when input comes from STDIN
  3. Write the piped content to a temp file first, then profile against that file

Example fix

# before
cat document.txt | languagetool -l en -p
# after
languagetool -l en -p document.txt
Defensive patterns

Strategy: validation

Validate before calling

boolean usesStdin = filename == null || filename.isEmpty() || "STDIN".equals(filename) || "-".equals(filename);
if (profileRules && usesStdin) {
  throw new IllegalArgumentException("Profiling requires a real file, not STDIN");
}

Type guard

static boolean isStdIn(String filename) {
  return filename == null || filename.isEmpty() || "STDIN".equals(filename) || "-".equals(filename);
}

Try / catch

try {
  runMain(args);
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("STDIN")) {
    System.err.println("Provide a file path when using -p/--profile");
    System.exit(2);
  }
  throw e;
}

Prevention

When it happens

Trigger: Running the tool in recursive/stdin-capable mode with profiling enabled and no filename (or '-' as filename), e.g. `cat file.txt | languagetool -p -l en` or omitting the filename while passing -p; runOnFileLineByLine is reached via runRecursive or main.

Common situations: Piping text into LanguageTool in a shell pipeline while leaving a profiling flag on; calling Main programmatically with "" or "STDIN" as filename together with profile=true.

Understand the failure class

Background: "Unknown argument", "Invalid value", and "must be one of": invalid CLI argument errors explained — this error's family across 35 libraries.

Related errors


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