{"record":{"id":"9db4af6a02b1dfff","repo":"iOfficeAI/OfficeCLI","slug":"min-value-is-invalid-on-a-log-scaled-axis-a-log","errorCode":null,"errorMessage":"min={value} is invalid on a log-scaled axis: a logarithmic axis minimum must be greater than 0.","messagePattern":"min=(.+?) is invalid on a log-scaled axis: a logarithmic axis minimum must be greater than 0\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Core/Chart/ChartHelper.Axis.cs","lineNumber":278,"sourceCode":"                case \"min\":\n                    // CONSISTENCY(chart/axis-role-write): the legacy `axismin` key\n                    // always targets the primary value axis. For role=value2 we must\n                    // write to the secondary axis directly to mirror BuildAxisNode's\n                    // Skip(1) read path. Same for max/crosses/crossesat below.\n                    // Category (date) and series axes must also write directly:\n                    // the legacy `axismin` fallback targets the primary VALUE\n                    // axis, which would clobber the wrong scaling.\n                    if (normalizedRole is \"value2\" or \"category\" or \"series\"\n                        && targetAxis is OpenXmlCompositeElement minAx2)\n                    {\n                        var scaling = minAx2.GetFirstChild<C.Scaling>();\n                        if (scaling != null)\n                        {\n                            var minV = ParseHelpers.SafeParseDouble(value, \"min\");\n                            // A log-scaled axis cannot have min <= 0 (Excel\n                            // refuses the file, 0x800A03EC).\n                            if (minV <= 0 && scaling.GetFirstChild<C.LogBase>() != null)\n                                throw new ArgumentException(\n                                    $\"min={value} is invalid on a log-scaled axis: a logarithmic axis minimum must be greater than 0.\");\n                            scaling.RemoveAllChildren<C.MinAxisValue>();\n                            // CT_Scaling order: logBase, orientation, max, min —\n                            // min is last, so append is always valid.\n                            scaling.AppendChild(new C.MinAxisValue { Val = minV });\n                        }\n                        directlyHandled.Add(key);\n                    }\n                    else\n                    {\n                        translated[\"axismin\"] = value;\n                    }\n                    break;\n\n                case \"max\":\n                    if (normalizedRole is \"value2\" or \"category\" or \"series\"\n                        && targetAxis is OpenXmlCompositeElement maxAx2)\n                    {","sourceCodeStart":260,"sourceCodeEnd":296,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/Chart/ChartHelper.Axis.cs#L260-L296","documentation":"When setting an axis minimum on a secondary or non-primary axis (value2, category, series roles), the library checks whether that axis has a LogBase child element. A logarithmic axis cannot have min <= 0 — Excel refuses the file (error 0x800A03EC). The check reads the raw string value, parses it via SafeParseDouble, and throws if <= 0 with an existing log scale.","triggerScenarios":"Setting axismin=0, axismin=-5, or any non-positive value on an axis that already has a C.LogBase element (log scaling enabled). This path is for non-primary value axes (value2, category, series roles); the primary value axis path is handled separately.","commonSituations":"Enabling log scale on a secondary axis then attempting to set min=0 (a common default for non-log axes). Copying a min=0 setting from a primary axis to a log-scaled secondary axis. Setting min before clearing the log scale.","solutions":["Set min to a positive value: axismin=1 or axismin=0.1.","If you need min=0, first disable log scaling on that axis: logbase=0 or logbase=false.","Verify which axis role you are targeting — value2, category, and series each hit this path independently."],"exampleFix":"// before\nlogbase=10\naxismin[value2]=0\n// after\nlogbase=10\naxismin[value2]=1","handlingStrategy":"validation","validationCode":"static bool IsLogAxisMinValid(double minVal, bool hasLogBase)\n    => !hasLogBase || minVal > 0;\n\n// Before setting axismin on a value2/category/series axis:\nvar scaling = axis.GetFirstChild<C.Scaling>();\nvar hasLog = scaling?.GetFirstChild<C.LogBase>() != null;\nvar minVal = ParseHelpers.SafeParseDouble(value, \"min\");\nif (!IsLogAxisMinValid(minVal, hasLog))\n    throw new InvalidOperationException(\"min must be > 0 on a log-scaled axis.\");","typeGuard":null,"tryCatchPattern":"try { axisSetter.Apply(\"axismin\", value); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"log-scaled axis\"))\n{\n    Console.Error.WriteLine($\"Disable log scale first (logbase=false) or use min > 0.\");\n}","preventionTips":["Check for an existing LogBase element before setting axismin to 0 or negative.","Set min to a positive value when log scale is enabled.","Disable log scale (logbase=false) before setting min=0."],"tags":["chart","axis","log-scale","range-check"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}