{"record":{"id":"cfe22e5b31ebd765","repo":"iOfficeAI/OfficeCLI","slug":"invalid-context-value-s-expected-a-finite","errorCode":null,"errorMessage":"Invalid '{context}' value '{s}'. Expected a finite number with optional unit (e.g. '12pt', '1.5x', '150%').","messagePattern":"Invalid '(.+?)' value '(.+?)'\\. Expected a finite number with optional unit \\(e\\.g\\. '12pt', '1\\.5x', '150%'\\)\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Core/SpacingConverter.cs","lineNumber":417,"sourceCode":"    {\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    }\n}\n","sourceCodeStart":399,"sourceCodeEnd":422,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/SpacingConverter.cs#L399-L422","documentation":"Thrown by SpacingConverter.ParseNumberAllowNegative when the numeric portion of a spacing/lineSpacing string is not a finite double: double.TryParse fails (non-numeric/garbage), or the result is NaN or Infinity. This is the bottom-of-stack parser every unit branch relies on, so any unparseable value bubbles here.","triggerScenarios":"Passing a non-numeric value, an unsupported unit (e.g. '12px'), an empty string, a locale-formatted number using comma as decimal ('1,5x'), or a stray suffix/whitespace inside the number portion like '1.5 x' or '12 pt ' where the unit strip leaves '12 ' handled, but 'abc' or '1.2.3' fails TrParse.","commonSituations":"Typo in the unit suffix ('px' vs 'pt'); locale decimal separator; copy-paste bringing an invisible character; passing a percentage into a field expecting a length.","solutions":["Use a supported format: a finite number with one of pt, cm, in, x, %, or a bare number, using a dot as the decimal separator.","Replace 'px' with 'pt'; replace ',' decimal with '.'.","Strip surrounding whitespace and stray characters before passing."],"exampleFix":"// before\nspacing = \"12px\"     // 'px' is not a supported unit\nspacing = \"1,5cm\"    // comma decimal separator rejected\n// after\nspacing = \"12pt\"\nspacing = \"1.5cm\"","handlingStrategy":"validation","validationCode":"static bool IsFiniteNumberWithOptionalUnit(string v)\n{\n    var t = v.Trim().TrimEnd('x','X','%');\n    foreach (var u in new[]{\"pt\",\"cm\",\"in\"}) if (t.EndsWith(u, System.StringComparison.OrdinalIgnoreCase)) { t = t[..^u.Length]; break; }\n    return double.TryParse(t.Trim(), System.Globalization.CultureInfo.InvariantCulture, out var n)\n           && !double.IsNaN(n) && !double.IsInfinity(n);\n}","typeGuard":null,"tryCatchPattern":"try { /* parse spacing */ }\ncatch (System.ArgumentException ex) when (ex.Message.Contains(\"finite number\"))\n{ /* tell user the accepted formats: 12pt / 1.5x / 150% / 0.5cm / 0.5in */ }","preventionTips":["Normalize locale decimals to invariant-culture '.' before parsing.","Whitelist unit suffixes in your UI/agent layer before they reach the converter.","Reject empty strings early."],"tags":["validation","parsing","spacing"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}