{"record":{"id":"94f7f75619932530","repo":"languagetool-org/languagetool","slug":"could-not-find-month-monthstr-94f7f7","errorCode":null,"errorMessage":"Could not find month '<monthStr>'","messagePattern":"Could not find month '<monthStr>'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"languagetool-language-modules/ru/src/main/java/org/languagetool/rules/ru/DateCheckFilter.java","lineNumber":70,"sourceCode":"  }\n\n  @SuppressWarnings({\"ControlFlowStatementWithoutBraces\", \"MagicNumber\"})\n  @Override\n  protected int getMonth(String monthStr) {\n    String mon = monthStr.toLowerCase();\n    if (mon.equals(\"январь\") || monthStr.equals(\"I\") || mon.equals(\"января\") || mon.equals(\"янв\")) return 1;\n    if (mon.equals(\"февраль\") || monthStr.equals(\"II\") ||  mon.equals(\"февраля\") || mon.equals(\"фев\")) return 2;\n    if (mon.equals(\"март\") || monthStr.equals(\"III\") || mon.equals(\"марта\") || mon.equals(\"мар\")) return 3;\n    if (mon.equals(\"апрель\") || monthStr.equals(\"IV\") || mon.equals(\"апреля\") || mon.equals(\"апр\")) return 4;\n    if (mon.equals(\"май\") || monthStr.equals(\"V\") || mon.equals(\"мая\")) return 5;\n    if (mon.equals(\"июнь\") || monthStr.equals(\"VI\") || mon.equals(\"июня\") || mon.equals(\"ин\")) return 6;\n    if (mon.equals(\"июль\") || monthStr.equals(\"VII\") || mon.equals(\"июля\") || mon.equals(\"ил\")) return 7;\n    if (mon.equals(\"август\") || monthStr.equals(\"VIII\") || mon.equals(\"августа\") || mon.equals(\"авг\")) return 8;\n    if (mon.equals(\"сентябрь\") || monthStr.equals(\"IX\") || mon.equals(\"сентября\") || mon.equals(\"сен\")) return 9;\n    if (mon.equals(\"октябрь\") || monthStr.equals(\"X\") || mon.equals(\"октября\") || mon.equals(\"окт\")) return 10;\n    if (mon.equals(\"ноябрь\") || monthStr.equals(\"XI\") || mon.equals(\"ноября\") || mon.equals(\"ноя\")) return 11;\n    if (mon.equals(\"декабрь\") || monthStr.equals(\"XII\") || mon.equals(\"декабря\") || mon.equals(\"дек\")) return 12;\n    throw new RuntimeException(\"Could not find month '\" + monthStr + \"'\");\n  }\n}\n","sourceCodeStart":52,"sourceCodeEnd":73,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-language-modules/ru/src/main/java/org/languagetool/rules/ru/DateCheckFilter.java#L52-L73","documentation":"DateCheckFilter.getMonth() maps Russian month names, inflected forms, abbreviations and Roman numerals (I–XII) to month numbers 1-12. If none of the hardcoded equals comparisons match, it throws this RuntimeException. It signals an unmatched month token in a date recognized by a Russian date rule.","triggerScenarios":"A Russian date rule matched a month token not covered by the list, e.g. an uncommon abbreviation ('июл' vs 'ил' inconsistency in the source), an inflected form ('июля' is covered but e.g. 'июлем' is not), a lowercase/uppercase variant mismatch, or a Roman numeral outside the covered set.","commonSituations":"Extending Russian date regexes in the ru module without syncing getMonth; test data or user text with unusual month inflections or abbreviations; typos ('ияюнь'); locale-dependent display names fed back into the parser.","solutions":["Add the unmatched token to the if-chain in DateCheckFilter.getMonth (DateCheckFilter.java:70) with the correct month number","Compare the token in the message against the covered strings and note the list mixes equals with full forms plus 'ил'/'сен' style abbreviations — add the missing abbreviation variant consistently for all 12 months","Tighten the corresponding regex rule so only month forms the filter knows about can match","Add a unit test in DateCheckFilterTest covering the new month token"],"exampleFix":"// before\nif (mon.equals(\"июль\") || monthStr.equals(\"VII\") || mon.equals(\"июля\") || mon.equals(\"ил\")) return 7;\n...\nthrow new RuntimeException(\"Could not find month '\" + monthStr + \"'\");\n// after\nif (mon.equals(\"июль\") || monthStr.equals(\"VII\") || mon.equals(\"июля\") || mon.startsWith(\"июл\")) return 7;\n...\nthrow new RuntimeException(\"Could not find month '\" + monthStr + \"'\");","handlingStrategy":"validation","validationCode":"private static final String[] MONTH_PREFIXES = {\"январ\",\"феврал\",\"март\",\"апрел\",\"мая\",\"июн\",\"июл\",\"авг\",\"сен\",\"окт\",\"ноя\",\"дек\"};\nboolean monthSupported(String token) {\n  String mon = token.toLowerCase(Locale.ROOT);\n  for (String p : MONTH_PREFIXES) if (mon.startsWith(p)) return true;\n  return token.matches(\"(?i)I{1,3}|IV|VI{0,3}|IX|X|XI|XII\");\n}","typeGuard":"boolean isRecognizedRussianMonth(String token) {\n  return token.toLowerCase(Locale.ROOT).matches(\"(январ|феврал|март|апрел|ма[йя]|июн|июл|авг|сен|окт|ноя|дек).*\")\n      || token.matches(\"[IVX]{1,4}\");\n}","tryCatchPattern":"try {\n  result = filter.filter(readings, args);\n} catch (RuntimeException e) {\n  if (e.getMessage() != null && e.getMessage().startsWith(\"Could not find month\")) {\n    log.warn(\"Skipping date match with unknown month token\");\n  } else { throw e; }\n}","preventionTips":["Test every month abbreviation and Roman numeral your date regexes can emit","Unify month handling between DateCheckFilter and DateFilterHelper","Normalize tokens to lowercase before matching","Add a round-trip test for all 12 months including inflected genitive forms"],"tags":["java","russian","nlp","date-parsing","languagetool"],"backgroundTag":"invalid-enum-value","analyzedSha":"2e990059ce67d5e2a0f7f7ca5d31160c6709df4b","analyzedAt":"2026-09-06T09:20:17.015Z","contentChangedAt":"2026-09-06T09:20:17.015Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}