{"record":{"id":"80b4d7260f12706c","repo":"iOfficeAI/OfficeCLI","slug":"xml-is-required-for-insertbefore","errorCode":null,"errorMessage":"--xml is required for insertbefore","messagePattern":"--xml is required for insertbefore","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Core/RawXmlHelper.cs","lineNumber":183,"sourceCode":"            {\n                case \"append\":\n                    if (xml == null) throw new ArgumentException(\"--xml is required for append\");\n                    var appendFragment = ParseFragment(xml, xDoc);\n                    foreach (var el in appendFragment)\n                        node.Add(el);\n                    affected++;\n                    break;\n\n                case \"prepend\":\n                    if (xml == null) throw new ArgumentException(\"--xml is required for prepend\");\n                    var prependFragment = ParseFragment(xml, xDoc);\n                    foreach (var el in prependFragment.AsEnumerable().Reverse())\n                        node.AddFirst(el);\n                    affected++;\n                    break;\n\n                case \"insertbefore\" or \"before\":\n                    if (xml == null) throw new ArgumentException(\"--xml is required for insertbefore\");\n                    RequireParent(node, \"insertbefore\");\n                    var beforeFragment = ParseFragment(xml, xDoc);\n                    // AddBeforeSelf lands each element immediately before the\n                    // anchor, i.e. AFTER everything inserted so far — forward\n                    // iteration preserves source order. (The reverse idiom is\n                    // insertafter-only; reversing here flipped a multi-element\n                    // fragment, splitting bookmarkStart/End pairs so the id\n                    // balancer synthesized a duplicate w:id end marker.)\n                    foreach (var el in beforeFragment)\n                        node.AddBeforeSelf(el);\n                    affected++;\n                    break;\n\n                case \"insertafter\" or \"after\":\n                    if (xml == null) throw new ArgumentException(\"--xml is required for insertafter\");\n                    RequireParent(node, \"insertafter\");\n                    var afterFragment = ParseFragment(xml, xDoc);\n                    // AddAfterSelf inserts immediately after `node`, so calling it","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/RawXmlHelper.cs#L165-L201","documentation":"Thrown when the action is 'insertbefore' (or alias 'before') but the xml argument is null. Insertbefore places the fragment as a preceding sibling of each matched element; it additionally calls RequireParent to ensure the matched node has a parent (you cannot insert a sibling before a root element). Without a fragment there is nothing to insert.","triggerScenarios":"RawXmlHelper.Execute(rootElement, xpath, \"insertbefore\", null) or RawXmlHelper.Execute(rootElement, xpath, \"before\", null). XPath matched, code entered the insertbefore/before case, xml == null.","commonSituations":"Caller invokes raw-set with action=insertbefore but omits --xml. Caller intended 'prepend' (first child) instead of 'insertbefore' (preceding sibling) and is confused about which requires xml. Argument was set conditionally and the condition was false.","solutions":["Provide a valid XML fragment to insert as a preceding sibling of each matched element.","If the matched element is the document root, switch to a different action — insertbefore requires a parent node.","Use 'insertbefore' for sibling-level insertion; use 'prepend' for child-level insertion (first child)."],"exampleFix":"// before\nRawXmlHelper.Execute(root, xpath, \"insertbefore\", null);\n\n// after\nRawXmlHelper.Execute(root, xpath, \"insertbefore\", \"<w:p><w:r><w:t>New paragraph</w:t></w:r></w:p>\");","handlingStrategy":"validation","validationCode":"var isInsertBefore = action.Equals(\"insertbefore\", StringComparison.OrdinalIgnoreCase)\n                     || action.Equals(\"before\", StringComparison.OrdinalIgnoreCase);\nif (isInsertBefore && string.IsNullOrEmpty(xml))\n    throw new ArgumentException(\"--xml is required for insertbefore\");\n\nRawXmlHelper.Execute(rootElement, xpath, action, xml);","typeGuard":null,"tryCatchPattern":"try\n{\n    RawXmlHelper.Execute(rootElement, xpath, \"insertbefore\", xml);\n}\ncatch (ArgumentException ex) when (ex.Message.Contains(\"--xml is required for insertbefore\"))\n{\n    Console.Error.WriteLine(\"Provide an XML fragment to insert as a preceding sibling.\");\n}","preventionTips":["Provide the xml fragment for insertbefore (preceding sibling).","Remember: insertbefore = sibling, prepend = first child.","Ensure the matched node has a parent — insertbefore can't work on root."],"tags":["xml","xpath","openxml","argument","raw-set"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}