iOfficeAI/OfficeCLI · error · InvalidOperationException

Batch item missing required 'command' field. Valid commands:

Error message

Batch item missing required 'command' field. Valid commands: get, query, set, add, remove, move, view, raw, validate. Example: {"command": "set", "path": "/Sheet1/A1", "props": {"value": "hello"}}

What it means

Thrown in the default branch of the batch command dispatch when item.Command is null or empty. An empty/null command string matches no case label and falls through to default; the guard then distinguishes 'missing' from 'unknown'. The message lists the core valid commands and the canonical JSON example.

Source

Thrown at src/officecli/CommandBuilder.cs:1244

                var (relId, partOut) = handler.AddPart(item.Parent, item.Type, props);
                return $"Created {item.Type} part: relId={relId} path={partOut}";
            }
            case "validate":
            {
                var errors = handler.Validate();
                if (errors.Count == 0) return "Validation passed: no errors found.";
                var lines = new List<string> { $"Found {errors.Count} validation error(s):" };
                foreach (var err in errors)
                {
                    lines.Add($"  [{err.ErrorType}] {err.Description}");
                    if (err.Path != null) lines.Add($"    Path: {err.Path}");
                    if (err.Part != null) lines.Add($"    Part: {err.Part}");
                }
                return string.Join("\n", lines);
            }
            default:
                if (string.IsNullOrEmpty(item.Command))
                    throw new InvalidOperationException(
                        "Batch item missing required 'command' field. " +
                        "Valid commands: get, query, set, add, remove, move, view, raw, validate. " +
                        "Example: {\"command\": \"set\", \"path\": \"/Sheet1/A1\", \"props\": {\"value\": \"hello\"}}");
                // A "command" containing whitespace is almost always a whole CLI
                // line stuffed into the verb field (e.g. "add /slide[1] --type
                // shape --prop ...") — the single most common batch-item mistake.
                // Diagnose it specifically and point at the item schema; a plain
                // unknown verb just gets the schema pointer.
                var batchHint = item.Command.Any(char.IsWhiteSpace)
                    ? " — that looks like a whole CLI line placed in \"command\". Use the bare verb only and put the"
                      + " rest in sibling fields, e.g. {\"command\":\"add\",\"parent\":\"/slide[1]\",\"type\":\"shape\","
                      + "\"props\":{...}}. Run `help batch` for the item schema."
                    : " Run `help batch` for the JSON item schema.";
                throw new InvalidOperationException($"Unknown command: '{item.Command}'. Valid commands: get, query, set, add, remove, move, swap, view, raw, validate.{batchHint}");
        }
    }

    private static Dictionary<string, string> ParsePropsArray(string[]? props)

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Add a 'command' field set to one of the valid verbs: get, query, set, add, remove, move, swap, view, raw, validate (and add-part/raw-set/import).
  2. Ensure the field is literally named 'command' (case-sensitivity depends on the deserializer — match the documented schema).
  3. Run 'help batch' to confirm the item schema if unsure of the field name.

Example fix

// before
{"path":"/Sheet1/A1","props":{"value":"hello"}}
// after
{"command":"set","path":"/Sheet1/A1","props":{"value":"hello"}}
Defensive patterns

Strategy: validation

Validate before calling

var validBatchCommands = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{ "get","query","set","add","remove","move","swap","view","raw","validate","add-part","raw-set","import" };
if (string.IsNullOrEmpty(item.Command) || !validBatchCommands.Contains(item.Command))
    throw new InvalidOperationException("Batch item needs a valid 'command' field.");

Type guard

static bool HasValidCommand(BatchItem i) =>
    !string.IsNullOrEmpty(i.Command) &&
    ValidBatchCommands.Contains(i.Command, StringComparer.OrdinalIgnoreCase);

Try / catch

try { result = Dispatch(item); }
catch (InvalidOperationException ex) when (ex.Message.Contains("missing required 'command' field"))
{ /* the item lacks a verb — re-issue with a command */ }

Prevention

When it happens

Trigger: A batch item with no 'command' key, or with "command":null/"". A caller that names the verb 'cmd', 'action', or 'op' instead of 'command'.

Common situations: An agent emits a bare {"path":...} item assuming the verb is implicit. A caller typo's the field name. A JSON deserializer that maps the verb to a different property name than 'command'.

Related errors


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