iOfficeAI/OfficeCLI · error · ArgumentException

'swap' command requires 'path' and 'path2' (or 'to') fields.

Error message

'swap' command requires 'path' and 'path2' (or 'to') fields. Example: {"command": "swap", "path": "/slide[1]", "path2": "/slide[2]"}

What it means

Thrown by the batch 'swap' command when item.Path is empty OR the second element (path2, falling back to legacy 'to') is empty. Swap is inherently a two-element operation; either side missing makes it meaningless. The code accepts both the canonical 'path2' key and the older 'to' key to tolerate agents that learned swap from the single-command MCP tool.

Source

Thrown at src/officecli/CommandBuilder.cs:1170

                InsertPosition? movePos = null;
                if (item.Index.HasValue) movePos = InsertPosition.AtIndex(item.Index.Value);
                else if (!string.IsNullOrEmpty(item.After)) movePos = InsertPosition.AfterElement(item.After);
                else if (!string.IsNullOrEmpty(item.Before)) movePos = InsertPosition.BeforeElement(item.Before);
                // Pass props to the 4-arg Move like the CLI and resident do; the
                // batch/MCP path previously dropped move-time properties.
                var resultPath = handler.Move(path, item.To, movePos, props.Count > 0 ? props : null);
                return $"Moved to {resultPath}";
            }
            case "swap":
            {
                // Second element: accept `path2` (canonical — the single-command
                // MCP tool and the CLI `swap path1 path2` both use it) or the
                // legacy `to`. Before path2 was carried, an agent that learned
                // swap from the single command produced a batch item that
                // silently failed the path-presence check below.
                var swapTo = !string.IsNullOrEmpty(item.Path2) ? item.Path2 : item.To;
                if (string.IsNullOrEmpty(item.Path) || string.IsNullOrEmpty(swapTo))
                    throw new ArgumentException("'swap' command requires 'path' and 'path2' (or 'to') fields. Example: {\"command\": \"swap\", \"path\": \"/slide[1]\", \"path2\": \"/slide[2]\"}");
                var (p1, p2) = handler switch
                {
                    OfficeCli.Handlers.PowerPointHandler ppt => ppt.Swap(item.Path, swapTo),
                    OfficeCli.Handlers.WordHandler word => word.Swap(item.Path, swapTo),
                    OfficeCli.Handlers.ExcelHandler excel => excel.Swap(item.Path, swapTo),
                    _ => throw new InvalidOperationException("swap not supported for this document type")
                };
                return $"Swapped {p1} <-> {p2}";
            }
            case "view":
            {
                var mode = item.Mode ?? "text";
                if (mode.ToLowerInvariant() is "html" or "h")
                {
                    if (handler is OfficeCli.Handlers.PowerPointHandler pptH)
                        return pptH.ViewAsHtml();
                    if (handler is OfficeCli.Handlers.ExcelHandler excelH)
                        return excelH.ViewAsHtml();

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Provide both 'path' and 'path2' (preferred) pointing at sibling elements of the same type.
  2. If you have a legacy caller using 'to', that is still accepted — set item.to to the second path.
  3. Confirm both paths are siblings (e.g. two /slide[N] entries) since Swap expects same-type siblings.

Example fix

// before
{"command":"swap","path":"/slide[1]"}
// after
{"command":"swap","path":"/slide[1]","path2":"/slide[2]"}
Defensive patterns

Strategy: validation

Validate before calling

var swapTo = !string.IsNullOrEmpty(item.Path2) ? item.Path2 : item.To;
if (string.IsNullOrEmpty(item.Path) || string.IsNullOrEmpty(swapTo))
    throw new ArgumentException("swap needs both 'path' and 'path2' (or 'to')");

Type guard

static bool HasSwapPair(BatchItem i) =>
    !string.IsNullOrEmpty(i.Path) &&
    (!string.IsNullOrEmpty(i.Path2) || !string.IsNullOrEmpty(i.To));

Try / catch

try { result = Dispatch(item); }
catch (ArgumentException ex) when (ex.Message.Contains("'swap' command requires"))
{ /* prompt caller for the second path */ }

Prevention

When it happens

Trigger: A swap item missing 'path', or missing both 'path2' and 'to'. Also when the second element is supplied under a different key like 'parent' or 'target'.

Common situations: An agent emits {"command":"swap","path":"/slide[1]"} forgetting the second slide. A caller uses 'to' for move but 'with' for swap, neither recognized.

Related errors


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