Humanizr/Humanizer · error · NotSupportedException
Culture '{Culture.Name}' does not support grammatical case '
Error message
Culture '{Culture.Name}' does not support grammatical case '{grammaticalCase}' for duration unit '{timeUnit}'. What it means
Thrown when a locale's duration case table marks a specific TimeUnit as Unsupported for the requested GrammaticalCase. This is a per-unit limitation: the culture supports the case in general (the earlier TryGetCase check passed), but this particular unit (e.g. Millisecond) has no case-inflected form. Reached only through the case-aware TimeSpanHumanize overloads that route into IGrammaticalCaseTimeSpanFormatter.TimeSpanHumanize.
Source
Thrown at src/Humanizer/Localisation/Formatters/DefaultFormatter.cs:180
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
{
LocalizedDurationCaseUnitKind.SameAsNominative => FormatCaseAwareNominative(timeUnit, unit),
LocalizedDurationCaseUnitKind.NotApplicable => throw new NotSupportedException(
$"Culture '{Culture.Name}' does not apply grammatical case '{grammaticalCase}' to duration unit '{timeUnit}'."),
LocalizedDurationCaseUnitKind.Unsupported => throw new NotSupportedException(
$"Culture '{Culture.Name}' does not support grammatical case '{grammaticalCase}' for duration unit '{timeUnit}'."),
_ => FormatCaseAwareTimeSpanPhrase(
timeUnit,
unit,
unitOverlay.Phrase!.Value)
};
}
/// <inheritdoc/>
public virtual string TimeSpanHumanize_Age()
{
return phraseTable.TimeSpanAge ?? "{0}";
}
/// <inheritdoc/>
public virtual string DataUnitHumanize(DataUnit dataUnit, double count, bool toSymbol = true)
{
if (TryFormatDataUnitFromPhraseTable(dataUnit, count, toSymbol, out var generated))View on GitHub (pinned to ffc2b77c0f)
Solutions
- Omit the grammaticalCase argument for that unit so it renders in the nominative default (FormatCaseAwareNominative).
- Choose a locale whose case table marks the target unit Supported or SameAsNominative rather than Unsupported.
- Wrap the call and fall back to the non-case Humanize overload on NotSupportedException.
Example fix
// before
var s = ts.Humanize(2, TimeUnit.Day, culture: new CultureInfo("uk"), grammaticalCase: GrammaticalCase.Genitive);
// after — fall back to nominative when the case is unsupported for a unit
string s;
try
{
s = ts.Humanize(2, TimeUnit.Day, culture: new CultureInfo("uk"), grammaticalCase: GrammaticalCase.Genitive);
}
catch (NotSupportedException)
{
s = ts.Humanize(2, TimeUnit.Day, culture: new CultureInfo("uk"));
} Defensive patterns
Strategy: try-catch
Validate before calling
// No public API exposes per-unit case support; validate by attempting the case-aware call and catching. // If you know the locale, prefer the nominative default for units you have not verified: var wantsCase = grammaticalCase != GrammaticalCase.Nominative; // (no pre-check available — use try-catch below)
Try / catch
string rendered;
try
{
rendered = ts.Humanize(maxUnit, minUnit, culture: culture, grammaticalCase: grammaticalCase);
}
catch (NotSupportedException)
{
// Locale does not inflect this unit for the requested case; fall back to nominative.
rendered = ts.Humanize(maxUnit, minUnit, culture: culture);
} Prevention
- Prefer the no-case Humanize overloads unless you have verified the locale inflects every TimeUnit you will emit.
- For Slavic/Turkic locales, test each TimeUnit you plan to surface (Millisecond and Week are commonly Unsupported).
- Keep a per-locale allowlist of (GrammaticalCase, TimeUnit) pairs you have confirmed Supported.
When it happens
Trigger: Calling timeSpan.Humanize(..., grammaticalCase: GrammaticalCase.Instrumental) or the 3-arg Humanize(TimeSpan, GrammaticalCase) for a locale whose LocaleDurationCaseTable has Units[(int)timeUnit].Kind == LocalizedDurationCaseUnitKind.Unsupported. Distinct from line 171 (whole case absent); line 180 fires when the case exists but the specific unit is flagged Unsupported.
Common situations: Requesting an instrumental/dative/genitive case under a Slavic or Turkic locale that declines some duration units (day, hour) but marks others (millisecond, week) unsupported; assuming a locale that 'has cases' supports them on every TimeUnit.
Related errors
- Custom formatter type '{GetType().FullName}' must explicitly
- Culture '{Culture.Name}' has no grammatical-case classificat
- Culture '{Culture.Name}' has an applicable grammatical case
- Culture '{Culture.Name}' does not support grammatical-case d
- Culture '{Culture.Name}' does not support grammatical case '
AI-assisted analysis of Humanizr/Humanizer@ffc2b77c0f (2026-08-13).
Data as JSON: /api/errors/16b3503211de65cf.
Report an issue: GitHub.