{"record":{"id":"23244594c02e62e5","repo":"iOfficeAI/OfficeCLI","slug":"invalid-majorunit-value-must-be-a-positive-nu","errorCode":null,"errorMessage":"Invalid majorUnit '{value}': must be a positive number (OOXML ST_AxisUnit > 0).","messagePattern":"Invalid majorUnit '(.+?)': must be a positive number \\(OOXML ST_AxisUnit > 0\\)\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Core/Chart/ChartHelper.Setter.cs","lineNumber":1044,"sourceCode":"                    // Schema order: logBase?, orientation, max?, min? — insert max after orientation\n                    var orient = scaling.GetFirstChild<C.Orientation>();\n                    if (orient != null) orient.InsertAfterSelf(maxEl);\n                    else scaling.PrependChild(maxEl);\n                    break;\n                }\n\n                case \"majorunit\":\n                {\n                    var plotArea2 = chart.GetFirstChild<C.PlotArea>();\n                    var valAxis = plotArea2?.GetFirstChild<C.ValueAxis>();\n                    if (valAxis == null) { unsupported.Add(key); break; }\n                    var mu = ParseHelpers.SafeParseDouble(value, \"majorunit\");\n                    // OOXML ST_AxisUnit: positive double. 0 or negative would\n                    // make Excel refuse to draw any tick on the axis (or, in\n                    // older builds, freeze the chart). Reject up front instead\n                    // of writing garbage that opens to a blank plot area.\n                    if (!(mu > 0))\n                        throw new ArgumentException($\"Invalid majorUnit '{value}': must be a positive number (OOXML ST_AxisUnit > 0).\");\n                    valAxis.RemoveAllChildren<C.MajorUnit>();\n                    InsertValAxChildInOrder(valAxis, new C.MajorUnit { Val = mu });\n                    break;\n                }\n\n                case \"minorunit\":\n                {\n                    var plotArea2 = chart.GetFirstChild<C.PlotArea>();\n                    var valAxis = plotArea2?.GetFirstChild<C.ValueAxis>();\n                    if (valAxis == null) { unsupported.Add(key); break; }\n                    var nu = ParseHelpers.SafeParseDouble(value, \"minorunit\");\n                    if (!(nu > 0))\n                        throw new ArgumentException($\"Invalid minorUnit '{value}': must be a positive number (OOXML ST_AxisUnit > 0).\");\n                    valAxis.RemoveAllChildren<C.MinorUnit>();\n                    InsertValAxChildInOrder(valAxis, new C.MinorUnit { Val = nu });\n                    break;\n                }\n","sourceCodeStart":1026,"sourceCodeEnd":1062,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/Chart/ChartHelper.Setter.cs#L1026-L1062","documentation":"Thrown when 'majorUnit' is not a positive number. OOXML ST_AxisUnit requires a double > 0; a value of 0 or negative makes Excel refuse to draw ticks (or freeze the chart in older builds). SafeParseDouble handles the non-numeric case separately; this throw fires only for a successfully parsed but non-positive number.","triggerScenarios":"SetChartProperties with { [\"majorUnit\"] = \"0\" }, \"-5\", or a parsed value that collapses to <= 0.","commonSituations":"Auto-generated tick interval of 0 from a data pipeline; sign error computing interval from data range; replaying a dump where the source chart had no majorUnit (empty) mis-encoded as 0.","solutions":["Pass a strictly positive majorUnit (e.g. 10, 0.5).","If you want Excel to auto-compute the interval, omit majorUnit instead of sending 0.","Compute the interval from the data range and guard against zero before calling Set."],"exampleFix":"// before\nSetChartProperties(part, new() { [\"majorUnit\"] = \"0\" });\n// after\nif (interval > 0)\n    SetChartProperties(part, new() { [\"majorUnit\"] = interval.ToString(CultureInfo.InvariantCulture) });","handlingStrategy":"validation","validationCode":"static bool IsValidAxisUnit(string v, out double unit) =>\n    double.TryParse(v, NumberStyles.Float, CultureInfo.InvariantCulture, out unit)\n    && unit > 0;","typeGuard":"static bool IsPositiveUnit(double v) => v > 0 && !double.IsInfinity(v);","tryCatchPattern":"try { SetChartProperties(part, props); }\ncatch (ArgumentException ex) when (ex.Message.StartsWith(\"Invalid majorUnit\"))\n{ /* omit majorUnit to let Excel auto-compute, or recompute from data */ }","preventionTips":["Compute intervals from the data range and guard against zero/negative before sending.","If no explicit interval is needed, omit majorUnit entirely.","Treat a computed interval of 0 as a data-pipeline bug, not a chart config."],"tags":["ooxml","chart","input-validation","axis","csharp"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}