{"record":{"id":"c6fb41a0e42b3e90","repo":"iOfficeAI/OfficeCLI","slug":"invalid-argument","errorCode":"invalid_argument","errorMessage":"--index, --after, and --before are mutually exclusive. Use only one.","messagePattern":"--index, --after, and --before are mutually exclusive\\. Use only one\\.","errorType":"error_code","errorClass":"CliException","httpStatus":null,"severity":"error","filePath":"src/officecli/CommandBuilder.Add.cs","lineNumber":75,"sourceCode":"        addCommand.SetAction(result => { var json = result.GetValue(jsonOption); return SafeRun(() =>\n        {\n            // CONSISTENCY(numfmt-warning): see CommandBuilder.Set.cs — collect\n            // Core-layer advisory warnings for the JSON envelope.\n            if (json) OfficeCli.Core.WarningContext.Begin();\n            var file = result.GetValue(addFileArg)!;\n            var parentPath = MsysPathHint.Restore(result.GetValue(addParentPathArg)!)!;\n            var type = result.GetValue(addTypeOpt);\n            var from = MsysPathHint.Restore(result.GetValue(addFromOpt));\n            var index = result.GetValue(addIndexOpt);\n            var after = MsysPathHint.Restore(result.GetValue(addAfterOpt));\n            var before = MsysPathHint.Restore(result.GetValue(addBeforeOpt));\n            var props = result.GetValue(addPropsOpt);\n            var force = result.GetValue(forceOption);\n\n            // Validate mutual exclusivity of --index, --after, --before\n            var posCount = (index.HasValue ? 1 : 0) + (after != null ? 1 : 0) + (before != null ? 1 : 0);\n            if (posCount > 1)\n                throw new OfficeCli.Core.CliException(\"--index, --after, and --before are mutually exclusive. Use only one.\")\n                {\n                    Code = \"invalid_argument\",\n                    Suggestion = \"Use --index for positional insert, or --after/--before for anchor-based insert.\"\n                };\n\n            InsertPosition? position = index.HasValue ? InsertPosition.AtIndex(index.Value)\n                : after != null ? InsertPosition.AfterElement(after)\n                : before != null ? InsertPosition.BeforeElement(before)\n                : null;\n            bool hadWarnings = false;\n\n            // Check document protection for .docx files\n            if (!force && file.Extension.Equals(\".docx\", StringComparison.OrdinalIgnoreCase))\n            {\n                var protectionError = CheckDocxProtection(file.FullName, parentPath, json);\n                if (protectionError != 0) return protectionError;\n            }\n","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/CommandBuilder.Add.cs#L57-L93","documentation":"Thrown by the `add` command when more than one of the positioning options --index, --after, --before is supplied. The posCount guard counts how many are set and rejects >1 with code `invalid_argument` and a Suggestion pointing to the correct single-option usage.","triggerScenarios":"`officecli add file.docx /body --type paragraph --index 0 --after /body/p[1]`, or `--after X --before Y`, or all three. Any combination where posCount exceeds 1.","commonSituations":"A user copies options from an example that used --after and pastes their own --index without removing it; an AI agent emits redundant positioning specifiers; a script template blindly includes all positioning flags.","solutions":["Keep exactly one positioning option: --index for a numeric slot, --after to anchor behind an element, or --before to anchor ahead.","Drop the redundant flag from your command line.","If you need anchor-based insert, use --after or --before alone; for positional, use --index alone."],"exampleFix":"# before\nofficecli add file.docx /body --type paragraph --index 0 --after /body/p[1]\n\n# after\nofficecli add file.docx /body --type paragraph --index 0","handlingStrategy":"validation","validationCode":"// Count positioning options before building the command line.\nint pos = (index.HasValue?1:0) + (after!=null?1:0) + (before!=null?1:0);\nif (pos > 1) throw new ArgumentException(\"Pass only one of --index/--after/--before\");","typeGuard":"// Narrow to at most one positioning specifier.\nstatic string? SinglePosition(int? index, string? after, string? before) =>\n    (index.HasValue, after, before) switch\n    {\n        (true, null, null) => $\"--index {index}\",\n        (false, string a, null) => $\"--after {a}\",\n        (false, null, string b) => $\"--before {b}\",\n        _ => null // invalid — caller errors\n    };","tryCatchPattern":null,"preventionTips":["Centralize positioning-flag selection in one helper so a command line is never assembled with two.","When templating add commands, default exactly one positioning source and clear the others."],"tags":["argument-validation","add","cli","mutual-exclusivity"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}