{"record":{"id":"0b1b216e90f1de4a","repo":"Humanizr/Humanizer","slug":"fixed-metric-precision-must-be-between-0-and-15","errorCode":null,"errorMessage":"Fixed metric precision must be between 0 and 15.","messagePattern":"Fixed metric precision must be between 0 and 15\\.","errorType":"validation","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"src/Humanizer/MetricNumeralExtensions.cs","lineNumber":43,"sourceCode":"\n/// <summary>\n/// Contains extension methods for changing a number to Metric representation (ToMetric)\n/// and from Metric representation back to the number (FromMetric)\n/// </summary>\npublic static class MetricNumeralExtensions\n{\n    const int Limit = 27;\n\n    static readonly double BigLimit = Math.Pow(10, Limit);\n    static readonly double SmallLimit = Math.Pow(10, -Limit);\n\n    static bool ShouldKeepTrailingZeros(MetricNumeralFormats? formats, int? decimals)\n    {\n        if (!decimals.HasValue || !formats.HasValue || !formats.Value.HasFlag(MetricNumeralFormats.KeepTrailingZeros))\n            return false;\n\n        if (decimals is < 0 or > 15)\n            throw new ArgumentOutOfRangeException(nameof(decimals), decimals, \"Fixed metric precision must be between 0 and 15.\");\n\n        return true;\n    }\n\n    static string FormatLongWithTrailingZeros(long input, int decimals, NumberFormatInfo nfi) =>\n        decimals > 0\n            ? input.ToString(nfi) + nfi.NumberDecimalSeparator + new string('0', decimals)\n            : input.ToString(nfi);\n\n    /// <summary>\n    /// Symbols is a list of every symbols for the Metric system.\n    /// </summary>\n    static readonly List<char>[] Symbols =\n    [\n        ['k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'],\n        ['m', 'μ', 'n', 'p', 'f', 'a', 'z', 'y']\n    ];\n","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/Humanizr/Humanizer/blob/ffc2b77c0f30d2fb176875841424379319d0ae9b/src/Humanizer/MetricNumeralExtensions.cs#L25-L61","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nvar s = value.ToMetric(MetricNumeralFormats.KeepTrailingZeros, decimals);\n\n// after\nvar safeDecimals = decimals is >= 0 and <= 15 ? decimals : 0;\nvar s = value.ToMetric(MetricNumeralFormats.KeepTrailingZeros, safeDecimals);","handlingStrategy":"validation","validationCode":"static bool IsValidMetricDecimals(int? decimals, MetricNumeralFormats? formats) =>\n    !decimals.HasValue ||\n    !formats.GetValueOrDefault().HasFlag(MetricNumeralFormats.KeepTrailingZeros) ||\n    decimals is >= 0 and <= 15;","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["metric","argument-validation","range-check"],"backgroundTag":null,"analyzedSha":"ffc2b77c0f30d2fb176875841424379319d0ae9b","analyzedAt":"2026-08-13T21:42:34.584Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}