{"record":{"id":"31853dfcfe189046","repo":"languagetool-org/languagetool","slug":"expected-semicolon-separated-input","errorCode":null,"errorMessage":"Expected semicolon-separated input: ","messagePattern":"Expected semicolon-separated input: ","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"languagetool-dev/src/main/java/org/languagetool/dev/bigdata/AutomaticProhibitedCompoundRuleEvaluator.java","lineNumber":82,"sourceCode":"    DirectoryReader reader = DirectoryReader.open(FSDirectory.open(luceneIndexDir.toPath()));\n    searcher = new IndexSearcher(reader);\n    InputStream confusionSetStream = JLanguageTool.getDataBroker().getFromResourceDirAsStream(\"/\" + LANGUAGE + \"/confusion_sets.txt\");\n    knownSets = new ConfusionSetLoader(language).loadConfusionPairs(confusionSetStream);\n  }\n\n  private void run(List<String> lines, File indexDir) throws IOException {\n    LanguageModel lm = new LuceneLanguageModel(indexDir);\n    ProhibitedCompoundRuleEvaluator evaluator = new ProhibitedCompoundRuleEvaluator(language, lm);\n    int lineCount = 0;\n    for (String line : lines) {\n      lineCount++;\n      if (line.contains(\"#\")) {\n        System.out.println(\"Ignoring: \" + line);\n        continue;\n      }\n      String[] parts = line.split(\";\\\\s*\");\n      if (parts.length != 2) {\n        throw new IOException(\"Expected semicolon-separated input: \" + line);\n      }\n      try {\n        int i = 1;\n        for (String part : parts) {\n          // compare pair-wise - maybe we should compare every item with every other item?\n          if (i < parts.length) {\n            runOnPair(evaluator, line, lineCount, lines.size(), removeComment(part), removeComment(parts[i]));\n          }\n          i++;\n        }\n      } catch (RuntimeException e) {\n        e.printStackTrace();\n      }\n    }\n    System.out.println(\"Done. Ignored items because they are already known: \" + ignored);\n  }\n\n  private String removeComment(String str) {","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-dev/src/main/java/org/languagetool/dev/bigdata/AutomaticProhibitedCompoundRuleEvaluator.java#L64-L100","documentation":"AutomaticProhibitedCompoundRuleEvaluator.run() reads input lines that must contain exactly two semicolon-separated fields (a compound pair). Lines with comments (#) are skipped, but any remaining line whose split on \";\\s*\" does not yield exactly 2 parts triggers this IOException, because pairwise comparison of the compound variants is impossible.","triggerScenarios":"An input line that isn't of the form 'word1;word2' — e.g. a single value with no semicolon, three or more semicolon-separated values, an empty or whitespace-only line slipping through, or a line whose '#' comment appears not at start so it isn't filtered by the contains(\"#\") check but changes field count expectations.","commonSituations":"Hand-edited compound lists with stray semicolons; CSV exported with commas instead of semicolons; trailing semicolons producing an empty third part; pasting lines with embedded comments or extra columns.","solutions":["Inspect the offending line printed in the message and correct it to exactly two semicolon-separated fields: word1;word2.","Trim the line and skip blank lines before splitting.","Handle comment lines robustly (skip lines starting with # or strip trailing comments) so partial comments don't corrupt the field count.","Make the parser tolerant: allow >=2 parts, or log-and-continue on malformed lines."],"exampleFix":"// before\nString[] parts = line.split(\";\\\\s*\");\nif (parts.length != 2) {\n  throw new IOException(\"Expected semicolon-separated input: \" + line);\n}\n// after\nString trimmed = line.trim();\nif (trimmed.isEmpty() || trimmed.startsWith(\"#\")) continue;\nString[] parts = trimmed.split(\";\\\\s*\");\nif (parts.length != 2) {\n  System.err.println(\"WARN: skipping malformed line: \" + line);\n  continue;\n}","handlingStrategy":"validation","validationCode":"String trimmed = line == null ? \"\" : line.trim();\nboolean valid = !trimmed.isEmpty() && !trimmed.startsWith(\"#\")\n    && trimmed.split(\";\\\\s*\").length == 2;\nif (!valid) throw new IllegalArgumentException(\"Bad compound pair line: \" + line);","typeGuard":null,"tryCatchPattern":"try {\n  evaluator.run(inputPath);\n} catch (IOException e) {\n  if (e.getMessage().startsWith(\"Expected semicolon-separated input\")) {\n    System.err.println(\"Fix line format (word1;word2): \" + e.getMessage());\n  }\n}","preventionTips":["Keep compound pair files strictly as 'word1;word2' per line, no comments mid-line","Trim and skip blank lines before parsing","Only treat lines starting with '#' as comments","Add a pre-flight lint that reports all malformed line numbers at once"],"tags":["java","input-validation","ioexception","parsing"],"backgroundTag":"invalid-argument-format","analyzedSha":"2e990059ce67d5e2a0f7f7ca5d31160c6709df4b","analyzedAt":"2026-09-06T09:20:17.015Z","contentChangedAt":"2026-09-06T09:20:17.015Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}