Humanizr/Humanizer · error · ArgumentOutOfRangeException
Fixed metric precision must be between 0 and 15.
Error message
Fixed metric precision must be between 0 and 15.
What it means
Thrown by ToMetric when the KeepTrailingZeros flag is set but the decimals argument falls outside 0-15. The trailing-zeros feature appends exactly 'decimals' fractional zeros to the output, so the value must fit a fixed-precision string format. Humanizer caps this at 15 to match the maximum practical precision of a double's decimal representation.
Source
Thrown at src/Humanizer/MetricNumeralExtensions.cs:43
/// <summary>
/// Contains extension methods for changing a number to Metric representation (ToMetric)
/// and from Metric representation back to the number (FromMetric)
/// </summary>
public static class MetricNumeralExtensions
{
const int Limit = 27;
static readonly double BigLimit = Math.Pow(10, Limit);
static readonly double SmallLimit = Math.Pow(10, -Limit);
static bool ShouldKeepTrailingZeros(MetricNumeralFormats? formats, int? decimals)
{
if (!decimals.HasValue || !formats.HasValue || !formats.Value.HasFlag(MetricNumeralFormats.KeepTrailingZeros))
return false;
if (decimals is < 0 or > 15)
throw new ArgumentOutOfRangeException(nameof(decimals), decimals, "Fixed metric precision must be between 0 and 15.");
return true;
}
static string FormatLongWithTrailingZeros(long input, int decimals, NumberFormatInfo nfi) =>
decimals > 0
? input.ToString(nfi) + nfi.NumberDecimalSeparator + new string('0', decimals)
: input.ToString(nfi);
/// <summary>
/// Symbols is a list of every symbols for the Metric system.
/// </summary>
static readonly List<char>[] Symbols =
[
['k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'],
['m', 'μ', 'n', 'p', 'f', 'a', 'z', 'y']
];
View on GitHub (pinned to ffc2b77c0f)
Solutions
- Clamp the decimals argument to the range 0-15 before calling ToMetric: var safeDecimals = Math.Clamp(decimals, 0, 15);
- If you don't need fixed trailing zeros, omit the KeepTrailingZeros flag or pass decimals: null.
- Validate the value with an explicit range check and surface a clear error to your caller before reaching Humanizer.
Example fix
// before var s = value.ToMetric(MetricNumeralFormats.KeepTrailingZeros, decimals); // after var safeDecimals = decimals is >= 0 and <= 15 ? decimals : 0; var s = value.ToMetric(MetricNumeralFormats.KeepTrailingZeros, safeDecimals);
Defensive patterns
Strategy: validation
Validate before calling
static bool IsValidMetricDecimals(int? decimals, MetricNumeralFormats? formats) =>
!decimals.HasValue ||
!formats.GetValueOrDefault().HasFlag(MetricNumeralFormats.KeepTrailingZeros) ||
decimals is >= 0 and <= 15; Prevention
- Always clamp decimals to 0-15 before passing to ToMetric with KeepTrailingZeros.
- Unit-test boundary values 0, 15, -1, and 16.
- Document the 0-15 limit wherever you expose a decimal-count setting.
When it happens
Trigger: Calling input.ToMetric(MetricNumeralFormats.KeepTrailingZeros, 16) or any value < 0 (e.g. -1). Only fires when both the formats parameter has the KeepTrailingZeros flag AND decimals has a value.
Common situations: Developer copies a precision constant from a UI formatter (e.g. decimal places = 17) into ToMetric. Off-by-one from a variable that can reach -1 before the call. Passing an unvalidated user-supplied decimal-count directly into ToMetric.
Related errors
- Empty or invalid Metric string.
- Argument must be non-negative.
- Fractional seconds support only midpoint rounding ToEven and
- Precision must be greater than zero.
- 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/0b1b216e90f1de4a.
Report an issue: GitHub.