{"record":{"id":"ff31fbaba6ae5500","repo":"iOfficeAI/OfficeCLI","slug":"xml-is-required-for-replace","errorCode":null,"errorMessage":"--xml is required for replace","messagePattern":"--xml is required for replace","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Core/RawXmlHelper.cs","lineNumber":219,"sourceCode":"                    // AddAfterSelf inserts immediately after `node`, so calling it\n                    // repeatedly against the SAME anchor REVERSES a multi-element\n                    // fragment (start,end → node,end,start). Iterate in REVERSE and\n                    // keep anchoring to `node`, mirroring insertbefore — each element\n                    // lands right after `node`, yielding source order. (Chaining the\n                    // anchor off the just-added node does NOT work: AddAfterSelf clones\n                    // a parented element, so the loop variable still points at the\n                    // detached fragment node, the chain breaks, and only the first\n                    // element reaches the document — silently dropping the rest of a\n                    // multi-marker fragment, e.g. a second tr-level bookmark.) A\n                    // reversed start/end pair also desynced the id-balancer into\n                    // duplicate bookmark ids.\n                    foreach (var el in afterFragment.AsEnumerable().Reverse())\n                        node.AddAfterSelf(el);\n                    affected++;\n                    break;\n\n                case \"replace\":\n                    if (xml == null) throw new ArgumentException(\"--xml is required for replace\");\n                    var replaceFragment = ParseFragment(xml, xDoc);\n                    node.ReplaceWith(replaceFragment.ToArray());\n                    affected++;\n                    break;\n\n                case \"remove\" or \"delete\":\n                    RequireParent(node, \"remove\");\n                    node.Remove();\n                    affected++;\n                    break;\n\n                case \"setattr\":\n                    if (xml == null) throw new ArgumentException(\"--xml is required for setattr (format: name=value)\");\n                    var eqIdx = xml.IndexOf('=');\n                    if (eqIdx <= 0) throw new ArgumentException(\"setattr format: name=value\");\n                    var attrName = xml[..eqIdx];\n                    var attrValue = xml[(eqIdx + 1)..];\n","sourceCodeStart":201,"sourceCodeEnd":237,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/RawXmlHelper.cs#L201-L237","documentation":"Thrown when the action is 'replace' but the xml argument is null. Replace swaps each matched element with the provided fragment (node.ReplaceWith). Without a fragment there is nothing to replace with. This is a destructive action — the original element is removed and substituted.","triggerScenarios":"RawXmlHelper.Execute(rootElement, xpath, \"replace\", null). XPath matched at least one element, code entered the replace case, xml == null.","commonSituations":"Caller invokes raw-set with action=replace but omits --xml. Caller intended 'remove' (delete without substitution) instead of 'replace'. Conditionally-built xml argument evaluated to null.","solutions":["Provide a valid XML fragment to replace each matched element with.","If you want to delete elements without substitution, use action='remove' instead of 'replace'.","Ensure the replacement fragment is well-formed XML — it's parsed by ParseFragment before insertion."],"exampleFix":"// before\nRawXmlHelper.Execute(root, xpath, \"replace\", null);\n\n// after\nRawXmlHelper.Execute(root, xpath, \"replace\", \"<w:pPr><w:pStyle w:val=\\\"Title\\\"/></w:pPr>\");","handlingStrategy":"validation","validationCode":"if (action.Equals(\"replace\", StringComparison.OrdinalIgnoreCase) && string.IsNullOrEmpty(xml))\n    throw new ArgumentException(\"--xml is required for replace\");\n\nRawXmlHelper.Execute(rootElement, xpath, action, xml);","typeGuard":null,"tryCatchPattern":"try\n{\n    RawXmlHelper.Execute(rootElement, xpath, \"replace\", xml);\n}\ncatch (ArgumentException ex) when (ex.Message == \"--xml is required for replace\")\n{\n    Console.Error.WriteLine(\"Provide a replacement XML fragment. Use 'remove' if you want to delete without replacement.\");\n}","preventionTips":["Provide the replacement XML fragment for replace.","Use 'remove' if you intended deletion without substitution.","Validate that the replacement fragment is well-formed XML."],"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"}