iOfficeAI/OfficeCLI · error · CliException

corrupt_batch

corrupt_batch

Error message

Dump-reader plugin '{plugin.Manifest.Name}' emitted a JSON array; protocol v1 requires JSONL (one BatchItem per line).

What it means

CliException (code 'corrupt_batch') thrown when a dump-reader plugin's stdout line begins with '[' — i.e. a top-level JSON array. Protocol v1 requires JSONL: exactly one BatchItem JSON object per line. The check runs in the per-line OnLine callback after BOM/whitespace trimming.

Source

Thrown at src/officecli/Core/Plugins/DumpReaderInvoker.cs:88

        var bufferedLines = new List<string>();

        try
        {
            void OnLine(string raw)
            {
                // Strip a per-line UTF-8 BOM (U+FEFF). Some Windows JSON
                // serializers emit BOM on every line of JSONL output, which
                // is technically RFC 8259 noncompliant but easy to absorb at
                // the host. Trim handles trailing whitespace and CR from a
                // CRLF-on-Windows plugin.
                var line = raw.TrimStart('').Trim();
                if (line.Length == 0) return;

                // Reject legacy top-level JSON arrays explicitly. Plugins that
                // emitted `[...]` under the old protocol now fail with a clear
                // error instead of being parsed as a malformed BatchItem.
                if (line[0] == '[')
                    throw new CliException(
                        $"Dump-reader plugin '{plugin.Manifest.Name}' emitted a JSON array; protocol v1 requires JSONL (one BatchItem per line).")
                    { Code = "corrupt_batch" };

                // Buffer raw line; defer JSON parse + replay to the
                // main-thread loop after plugin exit. JSON parse errors
                // surface there with the same item-index semantics.
                bufferedLines.Add(line);
            }

            var idle = plugin.Manifest.ResolveIdleTimeout("dump");
            var result = PluginProcess.Run(new PluginProcess.RunOptions
            {
                ExecutablePath = plugin.ExecutablePath,
                Arguments = new[] { "dump", sourceFullPath },
                IdleTimeoutSeconds = idle,
                OnStdoutLine = OnLine,
            });

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Update the plugin to emit one BatchItem per line (jsonl), e.g. foreach item: Console.WriteLine(JsonSerializer.Serialize(item)).
  2. Pin or upgrade the plugin to a version matching protocol v1.
  3. Confirm the plugin is not wrapping output in an array and is flushing each line.

Example fix

// before (plugin, v0)
var json = JsonSerializer.Serialize(allItems);
Console.WriteLine(json);

// after (plugin, v1)
foreach (var item in allItems)
    Console.WriteLine(JsonSerializer.Serialize(item));
Defensive patterns

Strategy: validation

Validate before calling

// In the plugin: validate output is JSONL before exiting.
foreach (var line in emitted) if (line.TrimStart().StartsWith("["))
    throw new InvalidOperationException("Output is a JSON array; emit JSONL.");

Try / catch

try { DumpReaderInvoker.Run(source, ext); }
catch (CliException ex) when (ex.Code == "corrupt_batch")
{ /* plugin emits JSON arrays — upgrade/rebuild the plugin */ }

Prevention

When it happens

Trigger: A plugin built against the legacy protocol emits `[{...},{...}]` as a single JSON array. Any line whose first char is '[' trips it.

Common situations: Upgrading the host to protocol v1 while the plugin still targets v0; a plugin author serializing a List<BatchItem> with one JsonSerializer.Serialize call instead of per-item writes.

Related errors


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