{"record":{"id":"399d51fb617a5800","repo":"languagetool-org/languagetool","slug":"a-separator-character-fsa-dict-separator-must-be-399d51","errorCode":null,"errorMessage":"A separator character (fsa.dict.separator) must be defined in the dictionary info file.","messagePattern":"A separator character \\(fsa\\.dict\\.separator\\) must be defined in the dictionary info file\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"languagetool-tools/src/main/java/org/languagetool/tools/SynthDictionaryBuilder.java","lineNumber":121,"sourceCode":"    String fileName = infoFile.getName();\n    int underscorePos = fileName.indexOf('_');\n    if (underscorePos == -1) {\n      throw new IllegalArgumentException(\"Please specify an .info file for a synthesizer as the second parameter, named '<xyz>_synth.info', with <xyz> being a language'\");\n    }\n    String baseName = fileName.substring(0, underscorePos);\n    if (baseName.equals(\"polish\")) {\n      return Pattern.compile(POLISH_IGNORE_REGEX);\n    }\n    return null;\n  }\n\n  private File reverseLineContent(File plainTextDictFile, Set<String> itemsToBeIgnored, Pattern ignorePosRegex) throws IOException {\n    File reversedFile = File.createTempFile(SynthDictionaryBuilder.class.getSimpleName() + \"_reversed\", \".txt\");\n    reversedFile.deleteOnExit();\n\n    String separator = getOption(\"fsa.dict.separator\");\n    if (separator == null || separator.trim().isEmpty()) {\n      throw new IOException(\"A separator character (fsa.dict.separator) must be defined in the dictionary info file.\");\n    }\n    \n    String encoding = getOption(\"fsa.dict.encoding\");\n    int posIgnoreCount = 0;\n    Scanner scanner = new Scanner(plainTextDictFile, encoding);\n    try (Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(reversedFile), encoding))) {\n      while (scanner.hasNextLine()) {\n        String line = scanner.nextLine();\n        if (itemsToBeIgnored.contains(line)) {\n          System.out.println(\"Ignoring: \" + line);\n          continue;\n        }\n        String[] parts = line.split(\"\\t\");\n        if (parts.length == 3) {\n          String posTag = parts[2];\n          if (ignorePosRegex != null && ignorePosRegex.matcher(posTag).find()) {\n            posIgnoreCount++;\n            continue;","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-tools/src/main/java/org/languagetool/tools/SynthDictionaryBuilder.java#L103-L139","documentation":"Configuration guard in SynthDictionaryBuilder: the synthesizer dictionary's .info file lacks fsa.dict.separator, so entries cannot be parsed/reversed correctly.","triggerScenarios":"Thrown at languagetool-tools/src/main/java/org/languagetool/tools/SynthDictionaryBuilder.java:121 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Add fsa.dict.separator=<char> to the synth dictionary .info file"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"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"}