Humanizr/Humanizer · error · ArgumentOutOfRangeException
Unsupported grammatical case.
Error message
Unsupported grammatical case.
What it means
Thrown in IGrammaticalCaseTimeSpanFormatter.TimeSpanHumanize when the grammaticalCase argument is not a defined member of the GrammaticalCase enum. The guard casts to uint and compares against (uint)GrammaticalCase.Causal (the last defined member), so any value above Causal or a negative cast-to-large-uint fails. The exception is ArgumentOutOfRangeException named 'grammaticalCase' with the offending value in the message.
Source
Thrown at src/Humanizer/Localisation/Formatters/DefaultFormatter.cs:144
}
return category;
}
string IGrammaticalCaseTimeSpanFormatter.TimeSpanHumanize(
TimeUnit timeUnit,
int unit,
GrammaticalCase grammaticalCase)
{
if (GetType().Assembly != typeof(DefaultFormatter).Assembly)
{
throw new NotSupportedException(
$"Custom formatter type '{GetType().FullName}' must explicitly implement {nameof(IGrammaticalCaseTimeSpanFormatter)} to support grammatical-case-aware durations.");
}
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)View on GitHub (pinned to ffc2b77c0f)
Solutions
- Validate with Enum.IsDefined(typeof(GrammaticalCase), grammaticalCase) before invoking the case-aware path.
- Parse the case from strings via Enum.TryParse<GrammaticalCase> and reject unknown tokens.
- When you only need the nominative form, use the non-case-aware TimeSpanHumanize(timeUnit, unit) overload.
Example fix
// before
var text = formatter.TimeSpanHumanize(unit, count, (GrammaticalCase)caseCode);
// after
if (!Enum.IsDefined(typeof(GrammaticalCase), caseCode))
throw new ArgumentOutOfRangeException(nameof(caseCode));
var text = formatter.TimeSpanHumanize(unit, count, (GrammaticalCase)caseCode); Defensive patterns
Strategy: validation
Validate before calling
if (!Enum.IsDefined(typeof(GrammaticalCase), grammaticalCase))
throw new ArgumentOutOfRangeException(nameof(grammaticalCase));
var text = caseFormatter.TimeSpanHumanize(timeUnit, unit, grammaticalCase); Type guard
static bool IsValidGrammaticalCase(GrammaticalCase c) => Enum.IsDefined(typeof(GrammaticalCase), c);
Try / catch
try { return caseFormatter.TimeSpanHumanize(timeUnit, unit, grammaticalCase); }
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "grammaticalCase")
{ return caseFormatter.TimeSpanHumanize(timeUnit, unit, GrammaticalCase.Nominative); } Prevention
- Validate GrammaticalCase at the boundary with Enum.IsDefined.
- Parse from strings with Enum.TryParse<GrammaticalCase>.
- Prefer the non-case-aware overload when you only need the nominative form.
When it happens
Trigger: Calling the case-aware formatter with (GrammaticalCase)999; passing a GrammaticalCase deserialized from an out-of-range integer; default(GrammaticalCase) is Nominative (0) and is valid so it will NOT throw.
Common situations: Configuration/serialization storing the case as a raw int; interop with another enum cast to GrammaticalCase; reflection-based callers that construct the value dynamically.
Related errors
- Specified argument was out of the range of valid values. (Pa
- Unsupported time unit.
- Specified argument was out of the range of valid values. (Pa
- Specified argument was out of the range of valid values. (Pa
- Specified argument was out of the range of valid values. (Pa
AI-assisted analysis of Humanizr/Humanizer@ffc2b77c0f (2026-08-13).
Data as JSON: /api/errors/67c0aa4b567e1a0f.
Report an issue: GitHub.