languagetool-org/languagetool · error
Could not find month '<monthStr>'
Error message
Could not find month '<monthStr>'
What it means
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.
Source
Thrown at languagetool-language-modules/ru/src/main/java/org/languagetool/rules/ru/DateCheckFilter.java:70
}
@SuppressWarnings({"ControlFlowStatementWithoutBraces", "MagicNumber"})
@Override
protected int getMonth(String monthStr) {
String mon = monthStr.toLowerCase();
if (mon.equals("январь") || monthStr.equals("I") || mon.equals("января") || mon.equals("янв")) return 1;
if (mon.equals("февраль") || monthStr.equals("II") || mon.equals("февраля") || mon.equals("фев")) return 2;
if (mon.equals("март") || monthStr.equals("III") || mon.equals("марта") || mon.equals("мар")) return 3;
if (mon.equals("апрель") || monthStr.equals("IV") || mon.equals("апреля") || mon.equals("апр")) return 4;
if (mon.equals("май") || monthStr.equals("V") || mon.equals("мая")) return 5;
if (mon.equals("июнь") || monthStr.equals("VI") || mon.equals("июня") || mon.equals("ин")) return 6;
if (mon.equals("июль") || monthStr.equals("VII") || mon.equals("июля") || mon.equals("ил")) return 7;
if (mon.equals("август") || monthStr.equals("VIII") || mon.equals("августа") || mon.equals("авг")) return 8;
if (mon.equals("сентябрь") || monthStr.equals("IX") || mon.equals("сентября") || mon.equals("сен")) return 9;
if (mon.equals("октябрь") || monthStr.equals("X") || mon.equals("октября") || mon.equals("окт")) return 10;
if (mon.equals("ноябрь") || monthStr.equals("XI") || mon.equals("ноября") || mon.equals("ноя")) return 11;
if (mon.equals("декабрь") || monthStr.equals("XII") || mon.equals("декабря") || mon.equals("дек")) return 12;
throw new RuntimeException("Could not find month '" + monthStr + "'");
}
}
View on GitHub (pinned to 2e990059ce)
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
Example fix
// before
if (mon.equals("июль") || monthStr.equals("VII") || mon.equals("июля") || mon.equals("ил")) return 7;
...
throw new RuntimeException("Could not find month '" + monthStr + "'");
// after
if (mon.equals("июль") || monthStr.equals("VII") || mon.equals("июля") || mon.startsWith("июл")) return 7;
...
throw new RuntimeException("Could not find month '" + monthStr + "'"); Defensive patterns
Strategy: validation
Validate before calling
private static final String[] MONTH_PREFIXES = {"январ","феврал","март","апрел","мая","июн","июл","авг","сен","окт","ноя","дек"};
boolean monthSupported(String token) {
String mon = token.toLowerCase(Locale.ROOT);
for (String p : MONTH_PREFIXES) if (mon.startsWith(p)) return true;
return token.matches("(?i)I{1,3}|IV|VI{0,3}|IX|X|XI|XII");
} Type guard
boolean isRecognizedRussianMonth(String token) {
return token.toLowerCase(Locale.ROOT).matches("(январ|феврал|март|апрел|ма[йя]|июн|июл|авг|сен|окт|ноя|дек).*")
|| token.matches("[IVX]{1,4}");
} Try / catch
try {
result = filter.filter(readings, args);
} catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Could not find month")) {
log.warn("Skipping date match with unknown month token");
} else { throw e; }
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Could not find day of week for '<dayStr>'
- Could not find day of week for '<dayStr>'
- Could not find month '<monthStr>'
- Could not tag and disambiguate '<token>'
- Could not find day of week for '" + dayStr + "'
AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06).
Data as JSON: /api/errors/94f7f75619932530.
Report an issue: GitHub.