{"record":{"id":"00d7892bc1db8e79","repo":"iOfficeAI/OfficeCLI","slug":"batch-commands-and-input-are-mutually-exclusi","errorCode":null,"errorMessage":"batch: --commands and --input are mutually exclusive. Pick one source.","messagePattern":"batch: --commands and --input are mutually exclusive\\. Pick one source\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/CommandBuilder.Batch.cs","lineNumber":211,"sourceCode":"                // EOF instantly (no payload → no warning); a pipe carrying a\n                // real second payload has data ready (warn); an open-but-idle\n                // pipe times out and is treated as no payload — batch never\n                // reads stdin on this path anyway, so nothing is lost. The\n                // possibly-blocked Peek thread is abandoned; the process\n                // exits normally.\n                try\n                {\n                    var stdinPeek = System.Threading.Tasks.Task.Run(() =>\n                    {\n                        try { return StdIn.Peek() != -1; }\n                        catch { return false; }\n                    });\n                    stdinHasInput = stdinPeek.Wait(TimeSpan.FromMilliseconds(50)) && stdinPeek.Result;\n                }\n                catch { /* keep IsInputRedirected verdict */ }\n            }\n            if (inlineCommands != null && inputFile != null)\n                throw new ArgumentException(\n                    \"batch: --commands and --input are mutually exclusive. Pick one source.\");\n            // '--input -' explicitly opts INTO stdin — don't emit the\n            // \"stdin will be ignored\" warning in that case, since stdin\n            // is exactly what will be read.\n            var inputIsStdinAlias = inputFile != null && inputFile.Name == \"-\";\n            if ((inlineCommands != null || (inputFile != null && !inputIsStdinAlias)) && stdinHasInput\n                && Environment.GetEnvironmentVariable(\"OFFICECLI_BATCH_ALLOW_STDIN_REDIRECT\") == null)\n            {\n                Console.Error.WriteLine(\n                    \"Warning: batch is reading from --commands/--input but stdin is also redirected; \"\n                    + \"stdin will be ignored. Pass only one source to silence this warning, or set \"\n                    + \"OFFICECLI_BATCH_ALLOW_STDIN_REDIRECT=1.\");\n            }\n            if (inlineCommands != null)\n            {\n                jsonText = inlineCommands;\n            }\n            else if (inputFile != null)","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/CommandBuilder.Batch.cs#L193-L229","documentation":"Thrown by the `batch` command when both --commands (inline JSON) and --input (file path) are supplied. The two are alternative input sources; providing both is ambiguous so an ArgumentException rejects it before any read happens (line 210-212).","triggerScenarios":"`officecli batch file.docx --commands '[{...}]' --input ops.json`. inlineCommands != null && inputFile != null triggers the throw.","commonSituations":"A script defaults to --input but a caller also passes --commands; an agent pastes an inline array while a config file path is still wired in; copy-paste merges two invocations.","solutions":["Choose one source: pass --commands for inline JSON, or --input for a file/stdin. Remove the other.","For files/stdin use --input <file> or --input - (stdin alias); for inline use --commands only.","If you need to merge, concatenate the JSON arrays into one source first."],"exampleFix":"# before\nofficecli batch file.docx --commands '[{\"command\":\"get\"}]' --input ops.json\n\n# after\nofficecli batch file.docx --input ops.json","handlingStrategy":"validation","validationCode":"// Ensure exactly one batch input source.\nif (inlineCommands != null && inputFile != null)\n    throw new ArgumentException(\"Pass --commands OR --input, not both\");","typeGuard":"// Guard: a single batch source is selected.\nstatic bool SingleBatchSource(string? inline, string? file) =>\n    (inline != null) ^ (file != null) || (inline == null && file == null);","tryCatchPattern":null,"preventionTips":["Use mutually exclusive CLI construction (one variable, cleared when the other is set) in wrappers.","Default to one source in scripts and never merge --commands from one call with --input from another."],"tags":["argument-validation","batch","cli","mutual-exclusivity"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}