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

  1. Fall back to the nominative TimeSpanHumanize(timeUnit, unit) overload when case-aware formatting is unsupported.
  2. Catch NotSupportedException around the case-aware call and degrade gracefully to a non-cased phrase.
  3. 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

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


AI-assisted analysis of Humanizr/Humanizer@ffc2b77c0f (2026-08-13). Data as JSON: /api/errors/feee8fb7d340f162. Report an issue: GitHub.