iOfficeAI/OfficeCLI · warning · JsonException

Expected StartObject for BatchItem

Error message

Expected StartObject for BatchItem

What it means

JsonException from BatchItemConverter.Read: an element of the batch list is not a JSON object. Each batch item must be a StartObject (e.g. {command:'set', ...}); a bare string, number, boolean, array, or null as a list element is rejected here.

Source

Thrown at src/officecli/BatchTypes.cs:74

    }

    public override void Write(Utf8JsonWriter writer, Dictionary<string, string> value, JsonSerializerOptions options)
    {
        writer.WriteStartObject();
        foreach (var kv in value)
            writer.WriteString(kv.Key, kv.Value);
        writer.WriteEndObject();
    }
}

internal class BatchItemConverter : JsonConverter<BatchItem>
{
    private static readonly LenientStringDictionaryConverter PropsConverter = new();

    public override BatchItem? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType != JsonTokenType.StartObject)
            throw new JsonException("Expected StartObject for BatchItem");

        var item = new BatchItem();
        while (reader.Read())
        {
            if (reader.TokenType == JsonTokenType.EndObject) return item;
            if (reader.TokenType != JsonTokenType.PropertyName)
                throw new JsonException("Expected PropertyName");
            var prop = reader.GetString()!;
            reader.Read();
            switch (prop.ToLowerInvariant())
            {
                case "command":
                case "op":
                    item.Command = reader.GetString() ?? "";
                    break;
                case "path": item.Path = reader.GetString(); break;
                case "parent": item.Parent = reader.GetString(); break;
                case "type": item.Type = reader.GetString(); break;

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Make every batch element an item object with a command/op key.
  2. Validate each element is a non-null object before serializing.
  3. Map shorthand command strings to {command: <name>, ...} objects.

Example fix

// before: await doc.batch(['set', 'get'])  // strings, not item objects
// after:  await doc.batch([{ command:'set', path:'/A1', props:{text:'x'} }, { command:'get', path:'/A1' }])
Defensive patterns

Strategy: type-guard

Validate before calling

// Ensure every batch element is an item object before batching
function validBatch(items) {
  return Array.isArray(items) && items.every(it => it && typeof it === 'object' && !Array.isArray(it) && typeof (it.command || it.op) === 'string');
}

Type guard

function isBatchItem(it) {
  return it !== null && typeof it === 'object' && !Array.isArray(it) && typeof (it.command || it.op) === 'string';
}

Prevention

When it happens

Trigger: A batch list containing a non-object element: ["set", {command:'set',...}] or [42] or [[...]]. Passing a flat array of command names instead of item objects.

Common situations: An agent/model emitting shorthand command strings instead of item objects; serializing a list of strings by mistake; a schema mismatch where the batch became an array of arrays.

Related errors


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