{"record":{"id":"d06e5204f9bbe004","repo":"Humanizr/Humanizer","slug":"culture-culture-name-does-not-support-grammati","errorCode":null,"errorMessage":"Culture '{Culture.Name}' does not support grammatical-case duration phrases.","messagePattern":"Culture '(.+?)' does not support grammatical-case duration phrases\\.","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"src/Humanizer/Localisation/Formatters/DefaultFormatter.cs","lineNumber":164,"sourceCode":"\n        if ((uint)timeUnit > (uint)TimeUnit.Year)\n        {\n            throw new ArgumentOutOfRangeException(nameof(timeUnit), timeUnit, \"Unsupported time unit.\");\n        }\n\n        var table = LocaleDurationCaseTableCatalog.Resolve(Culture)\n            ?? throw new NotSupportedException(\n                $\"Culture '{Culture.Name}' has no grammatical-case classification for duration phrases.\");\n\n        if (table.Classification == LocaleDurationCaseClassification.Unsupported)\n        {\n            throw new NotSupportedException(\n                $\"Culture '{Culture.Name}' has an applicable grammatical case system, but verified duration forms are unavailable.\");\n        }\n\n        if (table.Classification == LocaleDurationCaseClassification.NotApplicable)\n        {\n            throw new NotSupportedException(\n                $\"Culture '{Culture.Name}' does not support grammatical-case duration phrases.\");\n        }\n\n        if (!table.TryGetCase(grammaticalCase, out var caseOverlay))\n        {\n            throw new NotSupportedException(\n                $\"Culture '{Culture.Name}' does not support grammatical case '{grammaticalCase}' for duration phrases.\");\n        }\n\n        var unitOverlay = caseOverlay.Units[(int)timeUnit];\n        return unitOverlay.Kind switch\n        {\n            LocalizedDurationCaseUnitKind.SameAsNominative => FormatCaseAwareNominative(timeUnit, unit),\n            LocalizedDurationCaseUnitKind.NotApplicable => throw new NotSupportedException(\n                $\"Culture '{Culture.Name}' does not apply grammatical case '{grammaticalCase}' to duration unit '{timeUnit}'.\"),\n            LocalizedDurationCaseUnitKind.Unsupported => throw new NotSupportedException(\n                $\"Culture '{Culture.Name}' does not support grammatical case '{grammaticalCase}' for duration unit '{timeUnit}'.\"),\n            _ => FormatCaseAwareTimeSpanPhrase(","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/Humanizr/Humanizer/blob/ffc2b77c0f30d2fb176875841424379319d0ae9b/src/Humanizer/Localisation/Formatters/DefaultFormatter.cs#L146-L182","documentation":"Thrown when the culture's case table Classification is LocaleDurationCaseClassification.NotApplicable. This indicates the locale's language does not use grammatical case at all (e.g. English, most Romance languages), so asking for a case-aware duration is a category error. NotSupportedException is thrown because the operation is semantically inapplicable to the locale, not because the arguments are invalid.","triggerScenarios":"Casting a Western-locale DefaultFormatter to IGrammaticalCaseTimeSpanFormatter and requesting a specific GrammaticalCase; programmatically selecting a case for a locale whose language has no case system; generic code that always requests Genitive regardless of locale.","commonSituations":"Generic duration-formatting code that uniformly applies a GrammaticalCase to every locale; locale-agnostic UI that assumes case applies everywhere; mixing case-aware Slavic formatting with non-case Western locales in the same pipeline.","solutions":["Gate the case-aware call on locale: only request a GrammaticalCase for languages that have one, and use the plain overload otherwise.","Catch NotSupportedException and fall back to TimeSpanHumanize(timeUnit, unit).","Maintain a set of case-aware locale prefixes and skip the case path for the rest."],"exampleFix":"// before\nvar text = caseFormatter.TimeSpanHumanize(TimeUnit.Day, 1, GrammaticalCase.Genitive);\n\n// after\nstatic readonly HashSet<string> CaseAwareLocales = new() { \"ru\", \"pl\", \"uk\", \"cs\", \"sk\", \"lt\", \"lv\" };\nvar text = CaseAwareLocales.Contains(formatter.Culture.TwoLetterISOLanguageName)\n    ? caseFormatter.TimeSpanHumanize(TimeUnit.Day, 1, GrammaticalCase.Genitive)\n    : formatter.TimeSpanHumanize(TimeUnit.Day, 1);","handlingStrategy":"try-catch","validationCode":"// The NotApplicable classification is locale-driven. Skip the case path for\n// languages with no case system by consulting a locale allow-list.","typeGuard":"static readonly HashSet<string> CaseAwareLocales = new() { \"ru\", \"uk\", \"pl\", \"cs\", \"sk\", \"lt\", \"lv\" };\nstatic bool LocaleUsesGrammaticalCase(CultureInfo c) =>\n    CaseAwareLocales.Contains(c.TwoLetterISOLanguageName);","tryCatchPattern":"try { return caseFormatter.TimeSpanHumanize(unit, count, gCase); }\ncatch (NotSupportedException) { return formatter.TimeSpanHumanize(unit, count); }","preventionTips":["Only request GrammaticalCase for languages that have a case system.","Use a locale capability map rather than a global case enum loop.","Default Western locales to the plain TimeSpanHumanize overloads."],"tags":["localization","grammatical-case","formatter","not-supported","culture"],"backgroundTag":null,"analyzedSha":"ffc2b77c0f30d2fb176875841424379319d0ae9b","analyzedAt":"2026-08-13T21:42:34.584Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}