iOfficeAI/OfficeCLI · error · ArgumentException

batch item[{ni}] is null. Each entry must be a JSON object (

Error message

batch item[{ni}] is null. Each entry must be a JSON object (e.g. {"command":"get","path":"/"}).

What it means

Thrown when a batch array contains an explicit null entry (e.g. `[null]` or `[{...}, null]`). System.Text.Json deserializes these into a List<BatchItem> with a null slot that would later trip a NullReferenceException inside ExecuteBatchItem; the up-front loop at line 323-328 rejects them with a recognizable, index-pointed ArgumentException (tagged BUG-R40-B11).

Source

Thrown at src/officecli/CommandBuilder.Batch.cs:326

                        if (unknown.Count > 0)
                            throw new ArgumentException($"batch item[{ri}]: unknown field(s) {string.Join(", ", unknown.Select(f => $"\"{f}\""))}. Valid fields: {string.Join(", ", BatchItem.KnownFields)}");
                    }
                    ri++;
                }
            }

            var items = System.Text.Json.JsonSerializer.Deserialize<List<BatchItem>>(jsonText, BatchJsonContext.Default.ListBatchItem) ?? new();
            // NEWLINE-SEMANTICS-V2: strip meta items; rewrite legacy (\n = soft
            // break) docx dumps to the v2 encoding before execution.
            OfficeCli.Core.BatchCompat.PrepareForReplay(items, file.FullName);
            // BUG-R40-B11: explicit null entries (e.g. `[null]`) deserialize
            // to a List<BatchItem> with a null slot and trip a NRE deeper in
            // ExecuteBatchItem. Reject up-front with a recognizable error
            // pointing at the offending index.
            for (int ni = 0; ni < items.Count; ni++)
            {
                if (items[ni] == null)
                    throw new ArgumentException(
                        $"batch item[{ni}] is null. Each entry must be a JSON object (e.g. {{\"command\":\"get\",\"path\":\"/\"}}).");
            }
            if (items.Count == 0)
            {
                // BUG-R6-07: empty command array previously short-circuited
                // before the file-existence check, so
                //   officecli batch /missing.docx --commands '[]' --json
                // returned a clean zero-result success instead of the
                // expected file_not_found. Validate the target file
                // exists first so empty-array semantics match the
                // non-empty path's diagnostics.
                if (!file.Exists)
                    throw new CliException($"File not found: {file.FullName}")
                        { Code = "file_not_found" };
                // BUG-R7-09: in --json mode an empty/null batch input
                // previously skipped the {"success":...,"data":{...}}
                // envelope used by the populated-array path, so AI agents
                // saw a missing `success` key. Apply the same envelope

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Remove null entries from the batch array; every element must be a JSON object.
  2. Filter nulls before writing: `jq '[.[] | select(. != null)]' ops.json`.
  3. Ensure the producer never appends null on its error/fallback paths.

Example fix

// before
[{"command":"get"}, null]

// after
[{"command":"get"}]
Defensive patterns

Strategy: validation

Validate before calling

// Strip null entries before deserializing/sending.
using var d = System.Text.Json.JsonDocument.Parse(jsonText);
if (d.RootElement.EnumerateArray().Any(e => e.ValueKind == System.Text.Json.JsonValueKind.Null))
    throw new ArgumentException("batch array contains null entries");

Type guard

// Guard: no null slots.
static bool NoNullSlots(string json)
{
    try
    {
        using var d = System.Text.Json.JsonDocument.Parse(json);
        return !d.RootElement.EnumerateArray().Any(e => e.ValueKind == System.Text.Json.JsonValueKind.Null);
    }
    catch { return false; }
}

Prevention

When it happens

Trigger: `officecli batch file.docx --commands '[null]'` or `[{"command":"get"}, null]`. The deserialized list has a null slot caught by the ni-loop.

Common situations: An agent emits a trailing comma producing a null; a JSON template has an empty placeholder; programmatic array construction appends null on an error branch; JSON.stringify of an array with a null element.

Related errors


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