iOfficeAI/OfficeCLI · error · ArgumentException

Invalid spacing value '{value}'. Spacing must be non-negativ

Error message

Invalid spacing value '{value}'. Spacing must be non-negative.

What it means

Thrown by ParseWordSpacing when the parsed point value is negative. ParseWordSpacing converts spaceBefore/spaceAfter to unsigned Word twips (ST_TwipsMeasure, which is non-negative), so negatives are invalid for those slots. Note indent slots (left/right/firstLine) use ParseWordSpacingSigned instead, which allows negatives. ArgumentException.

Source

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

{
    private const double PointsPerCm = 72.0 / 2.54; // ~28.3465
    private const double PointsPerInch = 72.0;
    private const int TwipsPerPoint = 20; // 1 pt = 20 twips
    private const int WordAutoLineSpacingUnit = 240; // 240 twips = single line in Auto mode

    // ────────────────────────────────────────────────────────────────
    //  spaceBefore / spaceAfter  →  Word twips
    // ────────────────────────────────────────────────────────────────

    /// <summary>
    /// Parse a spacing value (spaceBefore/spaceAfter) to Word twips (uint).
    /// Accepts: "12pt", "0.5cm", "0.5in", or bare number (treated as twips for backward compat).
    /// </summary>
    public static uint ParseWordSpacing(string value)
    {
        var points = ParseSpacingToPoints(value, bareIsPoints: false);
        if (points < 0)
            throw new ArgumentException($"Invalid spacing value '{value}'. Spacing must be non-negative.");
        return (uint)Math.Round(points * TwipsPerPoint);
    }

    /// <summary>
    /// Signed twips variant for OOXML attributes typed `ST_SignedTwipsMeasure`:
    /// w:ind/@w:left, @w:right, @w:start, @w:end, @w:firstLine. Word documents
    /// commonly carry negative indents — e.g. `<w:ind w:right="-46">` so a
    /// table-of-contents page-number column overhangs the right margin. Real
    /// docs (gov.cn corpus) trip ParseWordSpacing's non-negative gate even
    /// though the OOXML schema explicitly allows negatives for these slots.
    /// Use this for indent slots only; spaceBefore/spaceAfter remain on the
    /// strict `ST_TwipsMeasure` path (the non-negative gate there catches
    /// the silent line-collapse failure mode that motivated it).
    /// </summary>
    public static int ParseWordSpacingSigned(string value)
    {
        var points = ParseSpacingToPointsSigned(value, bareIsPoints: false);
        return (int)Math.Round(points * TwipsPerPoint);

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Use a non-negative value for spaceBefore/spaceAfter (e.g. '12pt', '0').
  2. For indent slots that legitimately allow negatives (left/right/start/end/firstLine), use the signed path — the handlers already route those to ParseWordSpacingSigned.
  3. Verify you are setting the correct property: spacing vs indent.

Example fix

// before
set spacing spaceBefore=-12pt
// after
set spacing spaceBefore=12pt
Defensive patterns

Strategy: validation

Validate before calling

var pts = SpacingConverter.ParsePoints(value); // throws on negative
if (pts < 0) throw new ArgumentException($"Non-negative spacing required: {value}");
// For indent slots that allow negatives, use ParseWordSpacingSigned instead.

Try / catch

try { var twips = SpacingConverter.ParseWordSpacing(value); }
catch (ArgumentException ex) when (ex.Message.Contains("Spacing must be non-negative"))
{ /* use a non-negative value; switch to ParseWordSpacingSigned only for indent slots */ }

Prevention

When it happens

Trigger: Passing a negative spaceBefore/spaceAfter value such as '-12pt', '-0.5cm', or '-240' (bare twips) to a Word handler that routes through ParseWordSpacing (e.g. set spacing.spaceBefore).

Common situations: A user copies a negative value intended for an indent into a spacing field, or a script feeds a signed measurement into the non-negative spacing slot. Real docs carry negative indents but never negative spaceBefore/spaceAfter.

Related errors


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