{"record":{"id":"b7f76af01d65d50b","repo":"dotnet/BenchmarkDotNet","slug":"can-t-parse-threshold-threshold","errorCode":null,"errorMessage":"Can't parse threshold '{threshold}'","messagePattern":"Can't parse threshold '(.+?)'","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/BenchmarkDotNet/Columns/StatisticalTestColumn.cs","lineNumber":23,"sourceCode":"using Perfolizer.Mathematics.Common;\nusing Perfolizer.Mathematics.SignificanceTesting;\nusing Perfolizer.Mathematics.SignificanceTesting.MannWhitney;\nusing Perfolizer.Metrology;\n\nnamespace BenchmarkDotNet.Columns\n{\n    public class StatisticalTestColumn(Threshold threshold, SignificanceLevel? significanceLevel = null) : BaselineCustomColumn\n    {\n        private static readonly SignificanceLevel DefaultSignificanceLevel = SignificanceLevel.P1E5;\n\n        public static StatisticalTestColumn CreateDefault() => new(new PercentValue(10).ToThreshold());\n\n        public static StatisticalTestColumn Create(Threshold threshold, SignificanceLevel? significanceLevel = null) => new(threshold, significanceLevel);\n\n        public static StatisticalTestColumn Create(string threshold, SignificanceLevel? significanceLevel = null)\n        {\n            if (!Threshold.TryParse(UnitHelper.NormalizeUnits(threshold), out var parsedThreshold))\n                throw new ArgumentException($\"Can't parse threshold '{threshold}'\");\n            return new StatisticalTestColumn(parsedThreshold, significanceLevel);\n        }\n\n        public Threshold Threshold { get; } = threshold;\n        public SignificanceLevel SignificanceLevel { get; } = significanceLevel ?? DefaultSignificanceLevel;\n\n        public override string Id => $\"{nameof(StatisticalTestColumn)}/{Threshold}\";\n        public override string ColumnName => $\"MannWhitney({Threshold})\";\n\n        public override string GetValue(Summary summary, BenchmarkCase benchmarkCase, Statistics baseline, IReadOnlyDictionary<string, Metric> baselineMetrics,\n            Statistics current, IReadOnlyDictionary<string, Metric> currentMetrics, bool isBaseline)\n        {\n            if (baseline.Sample.Values.SequenceEqual(current.Sample.Values))\n                return \"Baseline\";\n            if (current.Sample.Size == 1 && baseline.Sample.Size == 1)\n                return \"?\";\n\n            // See ZeroMeasurementHelper: moving to Pragmastat.Toolkit.Compare2 would change the","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/dotnet/BenchmarkDotNet/blob/b515068b61ad1c9c9aa938b8ece4af1e7d6d85a3/src/BenchmarkDotNet/Columns/StatisticalTestColumn.cs#L5-L41","documentation":"StatisticalTestColumn.Create(string threshold) parses a threshold string (after normalizing units via UnitHelper.NormalizeUnits) using Threshold.TryParse. If parsing fails it throws ArgumentException. Threshold strings look like relative/absolute thresholds, e.g. \"10%\", \"5%\", or an absolute value with a unit. A malformed string, an unknown unit, or a non-numeric prefix fails TryParse.","triggerScenarios":"Calling StatisticalTestColumn.Create(\"abc\") or Create(\"10xyz\") with an unrecognized value/unit, or passing a user-supplied threshold string from config/CLI without validation.","commonSituations":"Building a Mann-Whitney statistical-test column from a config value, a CLI flag, or a JSON file whose threshold syntax is wrong (missing %, unknown unit, stray characters).","solutions":["Pre-validate with Threshold.TryParse(UnitHelper.NormalizeUnits(input), out var t) and only call Create when it returns true.","Use the strongly-typed overloads: Create(Threshold) / Create(PercentValue) / the constructor taking a Threshold, constructing it from a known-good PercentValue (new PercentValue(10).ToThreshold()).","Whitelist accepted units and formats before parsing external input.","Surface a clear validation error to the user instead of letting the ArgumentException propagate."],"exampleFix":"// before\nvar col = StatisticalTestColumn.Create(userThresholdString); // may throw\n\n// after\nif (!Threshold.TryParse(UnitHelper.NormalizeUnits(userThresholdString), out var t))\n    throw new FormatException($\"Invalid threshold '{userThresholdString}'. Use forms like '10%'.\");\nvar col = StatisticalTestColumn.Create(t);","handlingStrategy":"validation","validationCode":"if (!Threshold.TryParse(UnitHelper.NormalizeUnits(threshold), out var parsed))\n    throw new FormatException($\"Invalid threshold '{threshold}'. Use forms like '10%' or an absolute value with unit.\");\nreturn StatisticalTestColumn.Create(parsed);","typeGuard":"static bool IsValidThreshold(string s)\n    => Threshold.TryParse(UnitHelper.NormalizeUnits(s), out _);","tryCatchPattern":"try { return StatisticalTestColumn.Create(userThreshold); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"Can't parse threshold\"))\n{\n    // fall back to a default threshold, e.g. new PercentValue(10).ToThreshold()\n}","preventionTips":["Validate threshold strings with Threshold.TryParse before constructing the column.","Prefer the strongly-typed Create(Threshold)/Create(PercentValue) overloads when the value is known.","Whitelist accepted units/formats for user-supplied thresholds."],"tags":["statistics","threshold","parsing","columns","argument"],"backgroundTag":null,"analyzedSha":"b515068b61ad1c9c9aa938b8ece4af1e7d6d85a3","analyzedAt":"2026-08-13T19:12:24.196Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}