{"record":{"id":"460e693de9d5b544","repo":"iOfficeAI/OfficeCLI","slug":"invalid-context-value-s-spacing-values-mu","errorCode":null,"errorMessage":"Invalid '{context}' value '{s}'. Spacing values must be non-negative.","messagePattern":"Invalid '(.+?)' value '(.+?)'\\. Spacing values must be non-negative\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Core/SpacingConverter.cs","lineNumber":402,"sourceCode":"        if (trimmed.EndsWith(\"pt\", StringComparison.OrdinalIgnoreCase))\n            return ParseNumber(trimmed[..^2], \"spacing\");\n\n        if (trimmed.EndsWith(\"cm\", StringComparison.OrdinalIgnoreCase))\n            return ParseNumber(trimmed[..^2], \"spacing\") * PointsPerCm;\n\n        if (trimmed.EndsWith(\"in\", StringComparison.OrdinalIgnoreCase))\n            return ParseNumber(trimmed[..^2], \"spacing\") * PointsPerInch;\n\n        // Bare number\n        var num = ParseNumber(trimmed, \"spacing\");\n        return bareIsPoints ? num : num / TwipsPerPoint; // twips → points if Word\n    }\n\n    private static double ParseNumber(string s, string context)\n    {\n        var result = ParseNumberAllowNegative(s, context);\n        if (result < 0)\n            throw new ArgumentException(\n                $\"Invalid '{context}' value '{s}'. Spacing values must be non-negative.\");\n        return result;\n    }\n\n    /// <summary>\n    /// Parse a finite number without the non-negative gate. Used by the\n    /// Auto-rule lineSpacing paths, whose target attribute (w:line) is\n    /// ST_SignedTwipsMeasure and legitimately carries negatives in real docs.\n    /// </summary>\n    private static double ParseNumberAllowNegative(string s, string context)\n    {\n        var trimmed = s.Trim();\n        if (!double.TryParse(trimmed, CultureInfo.InvariantCulture, out var result)\n            || double.IsNaN(result) || double.IsInfinity(result))\n            throw new ArgumentException(\n                $\"Invalid '{context}' value '{s}'. Expected a finite number with optional unit (e.g. '12pt', '1.5x', '150%').\");\n        return result;\n    }","sourceCodeStart":384,"sourceCodeEnd":420,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/SpacingConverter.cs#L384-L420","documentation":"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.","triggerScenarios":"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'.","commonSituations":"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.","solutions":["Use a non-negative value for spaceBefore/spaceAfter (e.g. '12pt', '0pt' is allowed here).","If you genuinely need a negative value, you are on the wrong API: use the signed indent path (ParseWordSpacingSigned / ParsePointsSigned), not the spacing slot.","Clamp negatives to 0 before passing if 'auto' is the intent."],"exampleFix":"// before\nspaceBefore = \"-6pt\"   // spaceBefore/spaceAfter cannot be negative\n// after\nspaceBefore = \"0pt\"     // or a positive value; use a signed-indent API for negatives","handlingStrategy":"validation","validationCode":"static bool IsNonNegativeSpacing(string v)\n{\n    var t = v.Trim();\n    if (t.StartsWith(\"-\")) return false; // quick reject of leading minus\n    return double.TryParse(t.TrimEnd('p','t','c','m','i','n'), System.Globalization.CultureInfo.InvariantCulture, out var n) && n >= 0;\n}","typeGuard":null,"tryCatchPattern":"try { /* set spaceBefore/spaceAfter */ }\ncatch (System.ArgumentException ex) when (ex.Message.Contains(\"non-negative\"))\n{ /* clamp or report */ }","preventionTips":["Reserve negative values for indent slots, which use the signed parser.","Treat a -1 'auto' sentinel from legacy docs as 0 before replay into before/after.","Validate user-supplied spacing strings before they reach the OOXML writer."],"tags":["word","powerpoint","validation","spacing"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}