iOfficeAI/OfficeCLI · error · ArgumentException

--xml is required for insertafter

Error message

--xml is required for insertafter

What it means

Thrown when the action is 'insertafter' (or alias 'after') but the xml argument is null. Insertafter places the fragment as a following sibling of each matched element; it additionally calls RequireParent. The implementation iterates the fragment in reverse to preserve source order when anchoring multiple elements after the same node. Without a fragment there is nothing to insert.

Source

Thrown at src/officecli/Core/RawXmlHelper.cs:198

                    break;

                case "insertbefore" or "before":
                    if (xml == null) throw new ArgumentException("--xml is required for insertbefore");
                    RequireParent(node, "insertbefore");
                    var beforeFragment = ParseFragment(xml, xDoc);
                    // AddBeforeSelf lands each element immediately before the
                    // anchor, i.e. AFTER everything inserted so far — forward
                    // iteration preserves source order. (The reverse idiom is
                    // insertafter-only; reversing here flipped a multi-element
                    // fragment, splitting bookmarkStart/End pairs so the id
                    // balancer synthesized a duplicate w:id end marker.)
                    foreach (var el in beforeFragment)
                        node.AddBeforeSelf(el);
                    affected++;
                    break;

                case "insertafter" or "after":
                    if (xml == null) throw new ArgumentException("--xml is required for insertafter");
                    RequireParent(node, "insertafter");
                    var afterFragment = ParseFragment(xml, xDoc);
                    // AddAfterSelf inserts immediately after `node`, so calling it
                    // repeatedly against the SAME anchor REVERSES a multi-element
                    // fragment (start,end → node,end,start). Iterate in REVERSE and
                    // keep anchoring to `node`, mirroring insertbefore — each element
                    // lands right after `node`, yielding source order. (Chaining the
                    // anchor off the just-added node does NOT work: AddAfterSelf clones
                    // a parented element, so the loop variable still points at the
                    // detached fragment node, the chain breaks, and only the first
                    // element reaches the document — silently dropping the rest of a
                    // multi-marker fragment, e.g. a second tr-level bookmark.) A
                    // reversed start/end pair also desynced the id-balancer into
                    // duplicate bookmark ids.
                    foreach (var el in afterFragment.AsEnumerable().Reverse())
                        node.AddAfterSelf(el);
                    affected++;
                    break;

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Provide a valid XML fragment to insert as a following sibling of each matched element.
  2. Use 'insertafter' for sibling-level insertion; use 'append' for child-level insertion (last child).
  3. If the matched element is the document root, insertafter cannot work (no parent) — use a different action.

Example fix

// before
RawXmlHelper.Execute(root, xpath, "insertafter", null);

// after
RawXmlHelper.Execute(root, xpath, "insertafter", "<w:p><w:r><w:t>Inserted after</w:t></w:r></w:p>");
Defensive patterns

Strategy: validation

Validate before calling

var isInsertAfter = action.Equals("insertafter", StringComparison.OrdinalIgnoreCase)
                    || action.Equals("after", StringComparison.OrdinalIgnoreCase);
if (isInsertAfter && string.IsNullOrEmpty(xml))
    throw new ArgumentException("--xml is required for insertafter");

RawXmlHelper.Execute(rootElement, xpath, action, xml);

Try / catch

try
{
    RawXmlHelper.Execute(rootElement, xpath, "insertafter", xml);
}
catch (ArgumentException ex) when (ex.Message.Contains("--xml is required for insertafter"))
{
    Console.Error.WriteLine("Provide an XML fragment to insert as a following sibling.");
}

Prevention

When it happens

Trigger: RawXmlHelper.Execute(rootElement, xpath, "insertafter", null) or RawXmlHelper.Execute(rootElement, xpath, "after", null). XPath matched, code entered the insertafter/after case, xml == null.

Common situations: Caller invokes raw-set with action=insertafter but omits --xml. Caller confused 'append' (last child) with 'insertafter' (following sibling). Conditionally-built xml argument evaluated to null.

Related errors


AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13). Data as JSON: /api/errors/6e0256a6f61f8710. Report an issue: GitHub.