iOfficeAI/OfficeCLI · error · ArgumentException

Invalid 'lineSpacing' value '{raw}'. Line spacing must not b

Error message

Invalid 'lineSpacing' value '{raw}'. Line spacing must not be zero.

What it means

Thrown by the RequireNonZero local in ParseWordLineSpacing when a multiplier-form line spacing value ('1.5x', '150%', or a bare number) is exactly zero. Auto/multiplier line spacing maps to w:line (ST_SignedTwipsMeasure); negatives are schema-legal and allowed for round-tripping real styles, but zero is degenerate (BUG-R7-04) and rejected. ArgumentException.

Source

Thrown at src/officecli/Core/SpacingConverter.cs:160

        // BUG-R7-04: lineSpacing must not be zero. Zero produces degenerate
        // OOXML (w:spacing/@line=0 is undefined in MS-DOC) and Office silently
        // collapses to single-spacing — surface the error to the user instead.
        static double RequirePositive(double n, string raw)
        {
            if (n <= 0)
                throw new ArgumentException($"Invalid 'lineSpacing' value '{raw}'. Line spacing must be greater than 0.");
            return n;
        }

        // Auto/multiplier line spacing maps to w:line, which is
        // ST_SignedTwipsMeasure — negatives are schema-legal and real docs
        // carry them (e.g. <w:spacing w:line="-310" w:lineRule="auto"/> in a
        // style). Reject only zero (degenerate per BUG-R7-04); allow negative
        // so such styles round-trip instead of failing the whole add op.
        static double RequireNonZero(double n, string raw)
        {
            if (n == 0)
                throw new ArgumentException($"Invalid 'lineSpacing' value '{raw}'. Line spacing must not be zero.");
            return n;
        }

        // "1.5x" → multiplier (negative permitted under the Auto rule)
        if (trimmed.EndsWith("x", StringComparison.OrdinalIgnoreCase))
        {
            var num = RequireNonZero(ParseNumberAllowNegative(trimmed[..^1], "lineSpacing"), value);
            return ((int)Math.Round(num * WordAutoLineSpacingUnit), true);
        }

        // "150%" → multiplier (negative permitted under the Auto rule)
        if (trimmed.EndsWith("%", StringComparison.Ordinal))
        {
            var num = RequireNonZero(ParseNumberAllowNegative(trimmed[..^1], "lineSpacing"), value);
            return ((int)Math.Round(num / 100.0 * WordAutoLineSpacingUnit), true);
        }

        // "18pt" → fixed (Exact). "0pt" is allowed: paired with

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Use '1x' or '100%' for single-line spacing instead of 0.
  2. If a negative multiplier comes from an existing style, it will round-trip fine — no action needed.
  3. Ensure scripts do not default lineSpacing to 0; use a positive multiplier or a fixed pt value.

Example fix

// before
set paragraph lineSpacing=0x
// after
set paragraph lineSpacing=1x
Defensive patterns

Strategy: validation

Validate before calling

var trimmed = value.Trim();
if (trimmed.EndsWith("x") || trimmed.EndsWith("%") || (!trimmed.EndsWith("pt") && !trimmed.EndsWith("cm") && !trimmed.EndsWith("in")))
{
    var n = double.Parse(trimmed.TrimEnd('%','x'), CultureInfo.InvariantCulture);
    if (n == 0) throw new ArgumentException("lineSpacing multiplier must not be zero");
}
var r = SpacingConverter.ParseWordLineSpacing(value);

Try / catch

try { var (tw, mult) = SpacingConverter.ParseWordLineSpacing(value); }
catch (ArgumentException ex) when (ex.Message.Contains("must not be zero"))
{ /* use 1x/100% for single spacing; negative multipliers are allowed */ }

Prevention

When it happens

Trigger: Passing '0x', '0%', or a bare '0' as Word lineSpacing — these enter the multiplier ('x'/'%'/bare) branches which call RequireNonZero. A negative like '-1.5x' is accepted; only zero throws.

Common situations: A user passes 0 intending 'no extra spacing' or single-line, or a script defaults an unset field to 0. Real style sheets sometimes carry negative auto line values which are intentionally permitted here.

Related errors


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