iOfficeAI/OfficeCLI · error · System.ArgumentException

Invalid JSON for 'runs': {jex.Message}

Error message

Invalid JSON for 'runs': {jex.Message}

What it means

Thrown by ApplyRichTextToCell when the runs property is not valid JSON at all. JsonDocument.Parse raises a JsonException, which is caught and rewrapped as an ArgumentException with the parser's message. This fires before the array/object structure checks (492, 493), so any syntactically invalid JSON lands here.

Source

Thrown at src/officecli/Handlers/Excel/ExcelHandler.Add.Cells.cs:1466

                    {
                        var sv = p.Value.ValueKind switch
                        {
                            System.Text.Json.JsonValueKind.True => "true",
                            System.Text.Json.JsonValueKind.False => "false",
                            System.Text.Json.JsonValueKind.Null => "",
                            System.Text.Json.JsonValueKind.Number => p.Value.GetRawText(),
                            _ => p.Value.GetString() ?? ""
                        };
                        if (p.NameEquals("text")) text = sv;
                        else pd[p.Name] = sv;
                    }
                    OfficeCli.Core.ParseHelpers.ValidateXmlText(text, "richtext run text");
                    gatheredRuns.Add((text, pd));
                }
            }
            catch (System.Text.Json.JsonException jex)
            {
                throw new ArgumentException($"Invalid JSON for 'runs': {jex.Message}");
            }
        }
        else
        {
            var runKeys = properties.Keys
                .Where(k => k.StartsWith("run", StringComparison.OrdinalIgnoreCase) && k.Length > 3 &&
                            int.TryParse(k.AsSpan(3), out _))
                .OrderBy(k => int.Parse(k.AsSpan(3).ToString()))
                .ToList();
            foreach (var runKey in runKeys)
            {
                var runVal = properties[runKey];
                var colonIdx = runVal.IndexOf(':');
                string runText;
                string[] runProps;
                if (colonIdx >= 0)
                {
                    runText = runVal[..colonIdx];

View on GitHub (pinned to 1ced45e900)

Solutions

  1. If you meant legacy syntax, use run1=text:bold=true numbered keys instead of runs=.
  2. Validate the JSON with a linter before passing it; ensure double quotes and no trailing commas.
  3. Build the JSON with a serializer (System.Text.Json.JsonSerializer.Serialize) rather than hand-concatenating strings.

Example fix

// before
props["runs"] = "text:Hello;bold:true"; // legacy syntax in wrong key

// after
props["run1"] = "text:Hello;bold=true"; // legacy numbered syntax
Defensive patterns

Strategy: try-catch

Validate before calling

if (props.TryGetValue("runs", out var runsJson) && !string.IsNullOrWhiteSpace(runsJson))
{
    try { using var jdoc = System.Text.Json.JsonDocument.Parse(runsJson); }
    catch (System.Text.Json.JsonException) { throw new InvalidOperationException("runs is not valid JSON"); }
}
handler.Add(parentPath, "richtext", pos, props);

Type guard

static bool RunsJsonParses(string? json)
{
    if (string.IsNullOrWhiteSpace(json)) return true;
    try { using var _ = System.Text.Json.JsonDocument.Parse(json); return true; }
    catch (System.Text.Json.JsonException) { return false; }
}

Try / catch

try { handler.Add(parentPath, "richtext", pos, props); }
catch (ArgumentException ex) when (ex.Message.StartsWith("Invalid JSON for 'runs'"))
{ /* fix the JSON or switch to run1= legacy syntax */ }

Prevention

When it happens

Trigger: properties["runs"]="text:Hello;bold:true" (legacy syntax mistakenly put in runs=), or runs="{text" (truncated), or runs="'single quotes'". Any input that is not whitespace, not valid JSON, and not empty. Empty/whitespace runs skips the JSON branch entirely and falls to legacy runN parsing.

Common situations: User conflates the runs= JSON syntax with the legacy run1=text:prop=val syntax. Trailing commas, single quotes, unescaped quotes in the JSON. A shell quoting error that truncates the JSON.

Understand the failure class

Related errors


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