iOfficeAI/OfficeCLI · error · ArgumentException
comment runs: value must be a JSON array
Error message
comment runs: value must be a JSON array
What it means
Thrown by BuildCommentTextFromRuns when JsonNode.Parse succeeds but the result is not a JsonArray (e.g. it parsed as a JSON object, string, number, or scalar). The runs contract requires an array of run objects.
Source
Thrown at src/officecli/Handlers/Excel/ExcelHandler.Helpers.Node.cs:982
}
return arr.ToJsonString();
}
// Build a CommentText from a `runs=<json array>` value, one <r> per run
// carrying its own <rPr>. Run vocabulary mirrors rich-text cells
// (bold/italic/strike/underline/superscript/subscript/size/color/font) so
// the two paths share one input contract. Comment runs keep the Tahoma-9
// indexed-81 default for facets a run leaves unspecified.
internal static CommentText BuildCommentTextFromRuns(string runsJson)
{
System.Text.Json.Nodes.JsonArray? arr;
try { arr = System.Text.Json.Nodes.JsonNode.Parse(runsJson) as System.Text.Json.Nodes.JsonArray; }
catch (System.Text.Json.JsonException ex)
{
throw new ArgumentException($"comment runs: invalid JSON array — {ex.Message}");
}
if (arr == null)
throw new ArgumentException("comment runs: value must be a JSON array");
var ct = new CommentText();
foreach (var item in arr)
{
if (item is not System.Text.Json.Nodes.JsonObject o) continue;
var text = o["text"]?.GetValue<string>() ?? "";
OfficeCli.Core.ParseHelpers.ValidateXmlText(text, "comment run text");
var rPr = new RunProperties();
bool RunBool(string key) => o[key] is { } n
&& (n.GetValueKind() == System.Text.Json.JsonValueKind.True
|| (n.GetValueKind() == System.Text.Json.JsonValueKind.String && IsTruthy(n.GetValue<string>())));
if (RunBool("bold")) rPr.AppendChild(new Bold());
if (RunBool("italic")) rPr.AppendChild(new Italic());
if (RunBool("strike")) rPr.AppendChild(new Strike());
var uStr = o["underline"]?.GetValue<string>();
if (!string.IsNullOrEmpty(uStr) && !string.Equals(uStr, "none", StringComparison.OrdinalIgnoreCase))View on GitHub (pinned to 1ced45e900)
Solutions
- Wrap the value in an array: runs='[{...}]' even for a single run.
- Validate ValueKind == Array before sending (see validationCode).
- Re-check the schema example — runs is always a top-level JSON array, each element an object with at least a 'text' key.
Example fix
// before
string runs = "{\"text\":\"hi\"}"; // object, not array
// after
string runs = "[{\"text\":\"hi\"}]"; // array of one run Defensive patterns
Strategy: validation
Validate before calling
static bool IsRunsArray(string runsJson)
{
try
{
using var doc = System.Text.Json.JsonDocument.Parse(runsJson);
return doc.RootElement.ValueKind == System.Text.Json.JsonValueKind.Array;
}
catch { return false; }
} Type guard
null
Try / catch
try { BuildCommentTextFromRuns(runs); }
catch (ArgumentException ex) when (ex.Message == "comment runs: value must be a JSON array")
{ /* wrap single object into array, then retry */ } Prevention
- runs is an ARRAY of run objects — a bare object or scalar is rejected.
- Schema-check the producer: each element should be an object, non-object elements are silently skipped.
- Confirm the leading '[' and trailing ']' survive shell/JSON escaping.
When it happens
Trigger: runs='{"text":"hi"}' (a JSON object, not array), runs="\"hello\"" (a JSON string), runs='42' (a JSON number), or runs='true'. All parse fine but cast to JsonArray yields null.
Common situations: Passing a single run object instead of a one-element array; reusing a schema that wraps runs in an object; sending the text payload directly instead of an array wrapper.
Related errors
- comment runs: invalid JSON array — {ex.Message}
- Invalid '{propertyName}' value '{value}'. Expected a non-neg
- Invalid color value: '{value}'. Expected 6-digit hex RGB (e.
- Invalid source range: {sourceRef}
- Column {startCol} out of range (max: XFD)
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/61b7a69832e069a3.
Report an issue: GitHub.