iOfficeAI/OfficeCLI · error · ArgumentException

Invalid {lower} '{value}': must be a positive number (OOXML

Error message

Invalid {lower} '{value}': must be a positive number (OOXML ST_AxisUnit > 0).

What it means

The majorUnit/minorUnit setter applies to value axes only (value or value2 roles). The value is parsed as a double via SafeParseDouble, then checked to be strictly > 0 (OOXML ST_AxisUnit requires positive). A non-positive unit is invalid. The element (C.MajorUnit or C.MinorUnit) is then inserted in CT_ValAx schema order via InsertValAxChildInOrder.

Source

Thrown at src/officecli/Core/Chart/ChartHelper.Axis.cs:690

                case "majorunit":
                case "minorunit":
                {
                    // Schema: majorUnit / minorUnit only valid on value/value2.
                    // Without this direct-apply branch the role-scoped Set on
                    // role=value2 falls through to the chart-level case which
                    // always grabs the primary ValueAxis, so the secondary
                    // axis silently retained its old tick interval.
                    if (normalizedRole is not ("value" or "value2"))
                    {
                        directlyHandled.Add(key);
                        break;
                    }
                    if (targetAxis is OpenXmlCompositeElement axMu)
                    {
                        var unit = ParseHelpers.SafeParseDouble(value, lower);
                        if (!(unit > 0))
                            throw new ArgumentException(
                                $"Invalid {lower} '{value}': must be a positive number (OOXML ST_AxisUnit > 0).");
                        if (lower == "majorunit")
                        {
                            axMu.RemoveAllChildren<C.MajorUnit>();
                            InsertValAxChildInOrder(axMu, new C.MajorUnit { Val = unit });
                        }
                        else
                        {
                            axMu.RemoveAllChildren<C.MinorUnit>();
                            InsertValAxChildInOrder(axMu, new C.MinorUnit { Val = unit });
                        }
                    }
                    directlyHandled.Add(key);
                    break;
                }

                case "majorgridlines":
                case "minorgridlines":

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Use a strictly positive value: majorunit=10, minorunit=2.
  2. To use Excel's auto-calculation for major/minor unit, remove the element entirely (do not set it).
  3. Ensure the unit is smaller than the axis range to avoid invisible gridlines.

Example fix

// before
majorunit=0
// after
majorunit=10
// for auto unit, leave unset
// majorunit: (not set)
Defensive patterns

Strategy: validation

Validate before calling

static bool IsValidAxisUnit(string value)
{
    if (!double.TryParse(value, System.Globalization.NumberStyles.Float,
        System.Globalization.CultureInfo.InvariantCulture, out var unit))
        return false;
    return unit > 0;
}

Try / catch

try { axisSetter.Apply(lower, value); }
catch (ArgumentException ex) when (ex.Message.Contains("ST_AxisUnit"))
{
    Console.Error.WriteLine($"{ex.Message}\nMust be a positive number. Leave unset for auto.");
}

Prevention

When it happens

Trigger: Setting majorunit or minorunit to 0, a negative number, or a value that parses to <= 0: majorunit=0, minorunit=-5. Only fires for value/value2 axis roles.

Common situations: Using 0 expecting it to mean 'auto' (OOXML has no auto for major/minor unit via this element — leave the element unset for auto). Using a negative value from a calculation error. Setting unit on a category axis (silently ignored, does not throw).

Related errors


AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13). Data as JSON: /api/errors/061ec4003c3334fc. Report an issue: GitHub.