{"record":{"id":"1c8d64ebd4ba5539","repo":"iOfficeAI/OfficeCLI","slug":"batch-item-missing-required-command-field-valid","errorCode":null,"errorMessage":"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\"}}","messagePattern":"Batch item missing required 'command' field\\. Valid commands: get, query, set, add, remove, move, view, raw, validate\\. Example: (.+?)\\}","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/officecli/CommandBuilder.cs","lineNumber":1244,"sourceCode":"                var (relId, partOut) = handler.AddPart(item.Parent, item.Type, props);\n                return $\"Created {item.Type} part: relId={relId} path={partOut}\";\n            }\n            case \"validate\":\n            {\n                var errors = handler.Validate();\n                if (errors.Count == 0) return \"Validation passed: no errors found.\";\n                var lines = new List<string> { $\"Found {errors.Count} validation error(s):\" };\n                foreach (var err in errors)\n                {\n                    lines.Add($\"  [{err.ErrorType}] {err.Description}\");\n                    if (err.Path != null) lines.Add($\"    Path: {err.Path}\");\n                    if (err.Part != null) lines.Add($\"    Part: {err.Part}\");\n                }\n                return string.Join(\"\\n\", lines);\n            }\n            default:\n                if (string.IsNullOrEmpty(item.Command))\n                    throw new InvalidOperationException(\n                        \"Batch item missing required 'command' field. \" +\n                        \"Valid commands: get, query, set, add, remove, move, view, raw, validate. \" +\n                        \"Example: {\\\"command\\\": \\\"set\\\", \\\"path\\\": \\\"/Sheet1/A1\\\", \\\"props\\\": {\\\"value\\\": \\\"hello\\\"}}\");\n                // A \"command\" containing whitespace is almost always a whole CLI\n                // line stuffed into the verb field (e.g. \"add /slide[1] --type\n                // shape --prop ...\") — the single most common batch-item mistake.\n                // Diagnose it specifically and point at the item schema; a plain\n                // unknown verb just gets the schema pointer.\n                var batchHint = item.Command.Any(char.IsWhiteSpace)\n                    ? \" — that looks like a whole CLI line placed in \\\"command\\\". Use the bare verb only and put the\"\n                      + \" rest in sibling fields, e.g. {\\\"command\\\":\\\"add\\\",\\\"parent\\\":\\\"/slide[1]\\\",\\\"type\\\":\\\"shape\\\",\"\n                      + \"\\\"props\\\":{...}}. Run `help batch` for the item schema.\"\n                    : \" Run `help batch` for the JSON item schema.\";\n                throw new InvalidOperationException($\"Unknown command: '{item.Command}'. Valid commands: get, query, set, add, remove, move, swap, view, raw, validate.{batchHint}\");\n        }\n    }\n\n    private static Dictionary<string, string> ParsePropsArray(string[]? props)","sourceCodeStart":1226,"sourceCodeEnd":1262,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/CommandBuilder.cs#L1226-L1262","documentation":"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.","triggerScenarios":"A batch item with no 'command' key, or with \"command\":null/\"\". A caller that names the verb 'cmd', 'action', or 'op' instead of 'command'.","commonSituations":"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'.","solutions":["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).","Ensure the field is literally named 'command' (case-sensitivity depends on the deserializer — match the documented schema).","Run 'help batch' to confirm the item schema if unsure of the field name."],"exampleFix":"// before\n{\"path\":\"/Sheet1/A1\",\"props\":{\"value\":\"hello\"}}\n// after\n{\"command\":\"set\",\"path\":\"/Sheet1/A1\",\"props\":{\"value\":\"hello\"}}","handlingStrategy":"validation","validationCode":"var validBatchCommands = new HashSet<string>(StringComparer.OrdinalIgnoreCase)\n{ \"get\",\"query\",\"set\",\"add\",\"remove\",\"move\",\"swap\",\"view\",\"raw\",\"validate\",\"add-part\",\"raw-set\",\"import\" };\nif (string.IsNullOrEmpty(item.Command) || !validBatchCommands.Contains(item.Command))\n    throw new InvalidOperationException(\"Batch item needs a valid 'command' field.\");","typeGuard":"static bool HasValidCommand(BatchItem i) =>\n    !string.IsNullOrEmpty(i.Command) &&\n    ValidBatchCommands.Contains(i.Command, StringComparer.OrdinalIgnoreCase);","tryCatchPattern":"try { result = Dispatch(item); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"missing required 'command' field\"))\n{ /* the item lacks a verb — re-issue with a command */ }","preventionTips":["Always include the literal 'command' key in every batch item.","Validate the verb against the known set before dispatch.","Do not rename the field to 'cmd'/'action'/'op'."],"tags":["batch","missing-field","command","dispatch"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}