iOfficeAI/OfficeCLI · error · ArgumentException

Invalid '{context}' value '{s}'. Spacing values must be non-

Error message

Invalid '{context}' value '{s}'. Spacing values must be non-negative.

What it means

Thrown by the private SpacingConverter.ParseNumber helper when a parsed spacing value is negative. This gate backs the non-negative spacing slots (spaceBefore, spaceAfter, PPT spacing, XLSX margins) where negatives are schema-invalid. Indent slots deliberately bypass it via ParseNumberAllowNegative because ST_SignedTwipsMeasure legitimately carries negatives.

Source

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

        if (trimmed.EndsWith("pt", StringComparison.OrdinalIgnoreCase))
            return ParseNumber(trimmed[..^2], "spacing");

        if (trimmed.EndsWith("cm", StringComparison.OrdinalIgnoreCase))
            return ParseNumber(trimmed[..^2], "spacing") * PointsPerCm;

        if (trimmed.EndsWith("in", StringComparison.OrdinalIgnoreCase))
            return ParseNumber(trimmed[..^2], "spacing") * PointsPerInch;

        // Bare number
        var num = ParseNumber(trimmed, "spacing");
        return bareIsPoints ? num : num / TwipsPerPoint; // twips → points if Word
    }

    private static double ParseNumber(string s, string context)
    {
        var result = ParseNumberAllowNegative(s, context);
        if (result < 0)
            throw new ArgumentException(
                $"Invalid '{context}' value '{s}'. Spacing values must be non-negative.");
        return result;
    }

    /// <summary>
    /// Parse a finite number without the non-negative gate. Used by the
    /// Auto-rule lineSpacing paths, whose target attribute (w:line) is
    /// ST_SignedTwipsMeasure and legitimately carries negatives in real docs.
    /// </summary>
    private static double ParseNumberAllowNegative(string s, string context)
    {
        var trimmed = s.Trim();
        if (!double.TryParse(trimmed, CultureInfo.InvariantCulture, out var result)
            || double.IsNaN(result) || double.IsInfinity(result))
            throw new ArgumentException(
                $"Invalid '{context}' value '{s}'. Expected a finite number with optional unit (e.g. '12pt', '1.5x', '150%').");
        return result;
    }

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Use a non-negative value for spaceBefore/spaceAfter (e.g. '12pt', '0pt' is allowed here).
  2. If you genuinely need a negative value, you are on the wrong API: use the signed indent path (ParseWordSpacingSigned / ParsePointsSigned), not the spacing slot.
  3. Clamp negatives to 0 before passing if 'auto' is the intent.

Example fix

// before
spaceBefore = "-6pt"   // spaceBefore/spaceAfter cannot be negative
// after
spaceBefore = "0pt"     // or a positive value; use a signed-indent API for negatives
Defensive patterns

Strategy: validation

Validate before calling

static bool IsNonNegativeSpacing(string v)
{
    var t = v.Trim();
    if (t.StartsWith("-")) return false; // quick reject of leading minus
    return double.TryParse(t.TrimEnd('p','t','c','m','i','n'), System.Globalization.CultureInfo.InvariantCulture, out var n) && n >= 0;
}

Try / catch

try { /* set spaceBefore/spaceAfter */ }
catch (System.ArgumentException ex) when (ex.Message.Contains("non-negative"))
{ /* clamp or report */ }

Prevention

When it happens

Trigger: Passing a unit-qualified or bare negative value to spaceBefore/spaceAfter in Word (ParseWordSpacing) or PPT (ParsePptSpacing), to ParsePoints, or to any cm/in/pt branch of ParseSpacingToPoints. e.g. '-12pt', '-0.5cm', '-1in', or a bare '-240'.

Common situations: Copying a hanging-indent or negative margin value into a spaceBefore/spaceAfter slot; sign error; replaying a doc whose spacing carried a -1 'auto' sentinel that Word tolerates but is schema-invalid for before/after.

Related errors


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