Humanizr/Humanizer · error · NotSupportedException
Culture '{Culture.Name}' has an applicable grammatical case
Error message
Culture '{Culture.Name}' has an applicable grammatical case system, but verified duration forms are unavailable. What it means
Thrown when the culture's case table exists (Resolve returned non-null) but its Classification is LocaleDurationCaseClassification.Unsupported. This means the locale has an applicable grammatical-case system in principle, but Humanizer has no verified duration forms for it, so the case-aware path refuses to guess. It is a NotSupportedException signalling incomplete locale data rather than a bad argument.
Source
Thrown at src/Humanizer/Localisation/Formatters/DefaultFormatter.cs:158
}
if ((uint)grammaticalCase > (uint)GrammaticalCase.Causal)
{
throw new ArgumentOutOfRangeException(nameof(grammaticalCase), grammaticalCase, "Unsupported grammatical case.");
}
if ((uint)timeUnit > (uint)TimeUnit.Year)
{
throw new ArgumentOutOfRangeException(nameof(timeUnit), timeUnit, "Unsupported time unit.");
}
var table = LocaleDurationCaseTableCatalog.Resolve(Culture)
?? throw new NotSupportedException(
$"Culture '{Culture.Name}' has no grammatical-case classification for duration phrases.");
if (table.Classification == LocaleDurationCaseClassification.Unsupported)
{
throw new NotSupportedException(
$"Culture '{Culture.Name}' has an applicable grammatical case system, but verified duration forms are unavailable.");
}
if (table.Classification == LocaleDurationCaseClassification.NotApplicable)
{
throw new NotSupportedException(
$"Culture '{Culture.Name}' does not support grammatical-case duration phrases.");
}
if (!table.TryGetCase(grammaticalCase, out var caseOverlay))
{
throw new NotSupportedException(
$"Culture '{Culture.Name}' does not support grammatical case '{grammaticalCase}' for duration phrases.");
}
var unitOverlay = caseOverlay.Units[(int)timeUnit];
return unitOverlay.Kind switch
{View on GitHub (pinned to ffc2b77c0f)
Solutions
- Fall back to the nominative TimeSpanHumanize(timeUnit, unit) overload when case-aware formatting is unsupported.
- Catch NotSupportedException around the case-aware call and degrade gracefully to a non-cased phrase.
- If you maintain the locale, complete its duration case data so the classification moves out of Unsupported.
Example fix
// before
var text = caseFormatter.TimeSpanHumanize(TimeUnit.Hour, 3, GrammaticalCase.Genitive);
// after
string text;
try { text = caseFormatter.TimeSpanHumanize(TimeUnit.Hour, 3, GrammaticalCase.Genitive); }
catch (NotSupportedException) { text = formatter.TimeSpanHumanize(TimeUnit.Hour, 3); } Defensive patterns
Strategy: try-catch
Validate before calling
// Classification is internal; pre-checking requires a locale allow-list. // Validate against your own set of locales with verified duration forms before calling.
Type guard
static readonly HashSet<string> VerifiedDurationLocales = new() { /* populate from your data */ };
static bool LocaleHasVerifiedDurations(CultureInfo c) =>
VerifiedDurationLocales.Contains(c.Name); Try / catch
try { return caseFormatter.TimeSpanHumanize(unit, count, gCase); }
catch (NotSupportedException) { return formatter.TimeSpanHumanize(unit, count); } Prevention
- Maintain an allow-list of locales with complete duration case data.
- Fall back to nominative when duration forms are unverified.
- Track locale data completeness when upgrading Humanizer.
When it happens
Trigger: Calling case-aware duration formatting for a locale whose case system is recognized but whose duration phrases have not been authored/verified; a partially-localized locale that was shipped before its duration case data was completed.
Common situations: Upgrading Humanizer and hitting a locale whose classification flipped to Unsupported due to a data review; using a locale that maps to a supported case family but lacks vetted duration forms; contributing a locale without finishing the duration case overlay.
Related errors
- Culture '{Culture.Name}' has no grammatical-case classificat
- Culture '{Culture.Name}' does not support grammatical-case d
- Culture '{Culture.Name}' does not support grammatical case '
- Culture '{Culture.Name}' does not apply grammatical case '{g
- Custom formatter type '{GetType().FullName}' must explicitly
AI-assisted analysis of Humanizr/Humanizer@ffc2b77c0f (2026-08-13).
Data as JSON: /api/errors/feee8fb7d340f162.
Report an issue: GitHub.