{"record":{"id":"abc67c867fa4fd4e","repo":"iOfficeAI/OfficeCLI","slug":"expected-startobject-for-batchitem","errorCode":null,"errorMessage":"Expected StartObject for BatchItem","messagePattern":"Expected StartObject for BatchItem","errorType":"validation","errorClass":"JsonException","httpStatus":null,"severity":"warning","filePath":"src/officecli/BatchTypes.cs","lineNumber":74,"sourceCode":"    }\n\n    public override void Write(Utf8JsonWriter writer, Dictionary<string, string> value, JsonSerializerOptions options)\n    {\n        writer.WriteStartObject();\n        foreach (var kv in value)\n            writer.WriteString(kv.Key, kv.Value);\n        writer.WriteEndObject();\n    }\n}\n\ninternal class BatchItemConverter : JsonConverter<BatchItem>\n{\n    private static readonly LenientStringDictionaryConverter PropsConverter = new();\n\n    public override BatchItem? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n    {\n        if (reader.TokenType != JsonTokenType.StartObject)\n            throw new JsonException(\"Expected StartObject for BatchItem\");\n\n        var item = new BatchItem();\n        while (reader.Read())\n        {\n            if (reader.TokenType == JsonTokenType.EndObject) return item;\n            if (reader.TokenType != JsonTokenType.PropertyName)\n                throw new JsonException(\"Expected PropertyName\");\n            var prop = reader.GetString()!;\n            reader.Read();\n            switch (prop.ToLowerInvariant())\n            {\n                case \"command\":\n                case \"op\":\n                    item.Command = reader.GetString() ?? \"\";\n                    break;\n                case \"path\": item.Path = reader.GetString(); break;\n                case \"parent\": item.Parent = reader.GetString(); break;\n                case \"type\": item.Type = reader.GetString(); break;","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/BatchTypes.cs#L56-L92","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Make every batch element an item object with a command/op key.","Validate each element is a non-null object before serializing.","Map shorthand command strings to {command: <name>, ...} objects."],"exampleFix":"// before: await doc.batch(['set', 'get'])  // strings, not item objects\n// after:  await doc.batch([{ command:'set', path:'/A1', props:{text:'x'} }, { command:'get', path:'/A1' }])","handlingStrategy":"type-guard","validationCode":"// Ensure every batch element is an item object before batching\nfunction validBatch(items) {\n  return Array.isArray(items) && items.every(it => it && typeof it === 'object' && !Array.isArray(it) && typeof (it.command || it.op) === 'string');\n}","typeGuard":"function isBatchItem(it) {\n  return it !== null && typeof it === 'object' && !Array.isArray(it) && typeof (it.command || it.op) === 'string';\n}","tryCatchPattern":null,"preventionTips":["Build batch lists from item objects only, never bare strings/numbers.","Filter the list through isBatchItem() before sending.","Map shorthand command strings to {command: name} objects."],"tags":["batch","json","batch-item","deserialization","api-contract"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}