iOfficeAI/OfficeCLI · warning · JsonException

Expected PropertyName

Error message

Expected PropertyName

What it means

JsonException from BatchItemConverter.Read inside the item loop: after reading a property value, the next token was not a PropertyName. This signals a structurally malformed BatchItem object (a value appearing where a key is expected), distinct from error 18 (whole element not an object) and error 15 (props sub-object malformed).

Source

Thrown at src/officecli/BatchTypes.cs:81

        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;
                case "from": item.From = reader.GetString(); break;
                case "index": item.Index = reader.TokenType == JsonTokenType.Null ? null : reader.GetInt32(); break;
                case "after": item.After = reader.GetString(); break;
                case "before": item.Before = reader.GetString(); break;
                case "to": item.To = reader.GetString(); break;
                case "path2": item.Path2 = reader.GetString(); break;
                case "props": item.Props = PropsConverter.Read(ref reader, typeof(Dictionary<string, string>), options); break;

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Re-serialize batch items with a real JSON serializer so structure is guaranteed.
  2. Lint/parse the batch JSON before sending to catch structural errors early.
  3. Ensure each item is "key": value pairs, comma-separated, inside braces.

Example fix

// before: [{ command:'set' path:'/A1' props:{text:'x'} }]  // missing commas
// after:  const items = [{ command:'set', path:'/A1', props:{ text:'x' } }];
await doc.batch(items);
Defensive patterns

Strategy: validation

Validate before calling

// Round-trip the entire batch through a parser to catch structural errors
try { JSON.parse(JSON.stringify(items)); } catch (e) { throw new Error('Malformed batch: ' + e.message); }
await doc.batch(items);

Prevention

When it happens

Trigger: A batch item like {"command":"set" "path":"/A1"} (missing comma), {"command":"set", "path":"/A1" "extra"} (key with no value then a bare token), or any broken key/value sequence inside a BatchItem.

Common situations: Hand-built or templated JSON missing commas/colons; a serializer bug emitting values back-to-back; partial JSON pasted from docs.

Related errors


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