{"record":{"id":"f6e35a0966cbe158","repo":"Humanizr/Humanizer","slug":"culture-culture-name-does-not-apply-grammatica","errorCode":null,"errorMessage":"Culture '{Culture.Name}' does not apply grammatical case '{grammaticalCase}' to duration unit '{timeUnit}'.","messagePattern":"Culture '(.+?)' does not apply grammatical case '(.+?)' to duration unit '(.+?)'\\.","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"src/Humanizer/Localisation/Formatters/DefaultFormatter.cs","lineNumber":178,"sourceCode":"        }\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(\n                timeUnit,\n                unit,\n                unitOverlay.Phrase!.Value)\n        };\n    }\n\n    /// <inheritdoc/>\n    public virtual string TimeSpanHumanize_Age()\n    {\n        return phraseTable.TimeSpanAge ?? \"{0}\";\n    }\n\n    /// <inheritdoc/>\n    public virtual string DataUnitHumanize(DataUnit dataUnit, double count, bool toSymbol = true)","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/Humanizr/Humanizer/blob/ffc2b77c0f30d2fb176875841424379319d0ae9b/src/Humanizer/Localisation/Formatters/DefaultFormatter.cs#L160-L196","documentation":"Thrown when the requested grammatical case is supported by the locale, but for the specific TimeUnit the case-unit overlay is classified LocalizedDurationCaseUnitKind.NotApplicable. This is a finer-grained coverage gap: the locale supports the case in general, but that particular unit does not inflect for it (e.g. a locale where 'hour' has no distinct genitive form). NotSupportedException names both the case and the unit.","triggerScenarios":"Requesting a case for a TimeUnit whose overlay Kind is NotApplicable; mixing units where some inflect for the case and others do not; assuming uniform inflection across all units of a locale.","commonSituations":"Formatting compound durations ('2 hours 5 minutes') where minutes carry a genitive but hours do not (or vice versa) for the locale; reusing a single case across every TimeUnit in a loop; locale data that marks a unit as not-applicable pending verification.","solutions":["Per-unit fallback: when the case-aware call throws for a specific unit, fall back to the nominative form for that unit only.","Catch NotSupportedException around each unit's case-aware call and use TimeSpanHumanize(timeUnit, unit) for the failing unit.","If authoring locale data, mark the unit SameAsNominative instead of NotApplicable where the locale uses the nominative form."],"exampleFix":"// before\nforeach (var (unit, count) in parts)\n    phrase += caseFormatter.TimeSpanHumanize(unit, count, grammaticalCase); // throws on one unit\n\n// after\nforeach (var (unit, count) in parts)\n{\n    try { phrase += caseFormatter.TimeSpanHumanize(unit, count, grammaticalCase); }\n    catch (NotSupportedException) { phrase += formatter.TimeSpanHumanize(unit, count); }\n}","handlingStrategy":"try-catch","validationCode":"// Per-unit applicability is internal; the practical guard is a per-unit\n// try/catch with nominative fallback for the offending unit.","typeGuard":null,"tryCatchPattern":"foreach (var (unit, count) in parts)\n{\n    try { phrase += caseFormatter.TimeSpanHumanize(unit, count, gCase); }\n    catch (NotSupportedException) { phrase += formatter.TimeSpanHumanize(unit, count); }\n}","preventionTips":["Handle case-aware formatting per unit, not just per phrase.","Provide a nominative fallback for units that do not inflect for the case.","When authoring locale data, prefer SameAsNominative over NotApplicable where the nominative form is acceptable."],"tags":["localization","grammatical-case","timeunit","formatter","not-supported","culture"],"backgroundTag":null,"analyzedSha":"ffc2b77c0f30d2fb176875841424379319d0ae9b","analyzedAt":"2026-08-13T21:42:34.584Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}