iOfficeAI/OfficeCLI · error · System.ArgumentException
Anchor sheet '{aSegs[0]}' must match target sheet '{colSheet
Error message
Anchor sheet '{aSegs[0]}' must match target sheet '{colSheetName}' What it means
Thrown by AddCol when resolving a --before/--after anchor for a column insertion. The anchor path's sheet segment (aSegs[0]) does not match the target sheet name (colSheetName) that the column is being added to. The comparison is OrdinalIgnoreCase, so it is purely a name mismatch, not a casing issue. This guard prevents inserting into one sheet using an anchor that lives in a different sheet, which would silently produce a wrong column index.
Source
Thrown at src/officecli/Handlers/Excel/ExcelHandler.Add.Cells.cs:1050
var colSegments = parentPath.TrimStart('/').Split('/', 2);
var colSheetName = colSegments[0];
var colWorksheet = FindWorksheet(colSheetName)
?? throw new ArgumentException($"Sheet not found: {colSheetName}");
// Resolve --before / --after anchors, mirroring AddRow. Anchor must
// be /<sheetName>/col[L] in the same sheet; --before takes the
// anchor's slot, --after lands one column to the right.
int? index = position?.Index;
if (index == null && position != null && (position.After != null || position.Before != null))
{
int FindAnchorColIndex(string anchorPath)
{
var aSegs = anchorPath.TrimStart('/').Split('/', 2);
if (aSegs.Length < 2)
throw new ArgumentException(
$"Anchor must be a column path like /{colSheetName}/col[L], got: {anchorPath}");
if (!aSegs[0].Equals(colSheetName, StringComparison.OrdinalIgnoreCase))
throw new ArgumentException(
$"Anchor sheet '{aSegs[0]}' must match target sheet '{colSheetName}'");
var am = Regex.Match(aSegs[1], @"^col\[([A-Za-z]+)\]$", RegexOptions.IgnoreCase);
if (!am.Success)
throw new ArgumentException(
$"Anchor must be a column path like /{colSheetName}/col[L], got: {anchorPath}");
return ColumnNameToIndex(am.Groups[1].Value.ToUpperInvariant());
}
if (position.Before != null) index = FindAnchorColIndex(position.Before);
else index = FindAnchorColIndex(position.After!) + 1;
}
// Determine insert column: index (1-based) or name/letter from properties
// CONSISTENCY(col-letter-prop): accept col=, letter=, column= as aliases of name=
// matching how `colbreak` (case "colbreak" above) accepts col/column/index.
string insertColName;
string? colLetterProp = null;
if (properties.TryGetValue("name", out var colNameProp) && !string.IsNullOrEmpty(colNameProp))
colLetterProp = colNameProp;View on GitHub (pinned to 1ced45e900)
Solutions
- Make the anchor path's sheet segment identical to the target sheet: use /<colSheetName>/col[L] for both --before and --after.
- If you intend to anchor relative to a column in another sheet, insert the column there instead, or compute the absolute numeric index and pass it via position.Index to bypass anchor resolution entirely.
- Verify the sheet name spelling against the workbook with a Get on /SheetName before constructing the position.
Example fix
// before
var pos = new InsertPosition { Before = "/Sheet2/col[B]" };
handler.Add("/Sheet1", "col", pos, props);
// after
var pos = new InsertPosition { Before = "/Sheet1/col[B]" };
handler.Add("/Sheet1", "col", pos, props); Defensive patterns
Strategy: validation
Validate before calling
string targetSheet = "Sheet1";
string anchor = "/Sheet1/col[B]";
var aSegs = anchor.TrimStart('/').Split('/', 2);
if (aSegs.Length < 2 || !aSegs[0].Equals(targetSheet, StringComparison.OrdinalIgnoreCase))
throw new InvalidOperationException($"Anchor sheet must be {targetSheet}");
handler.Add("/" + targetSheet, "col", new InsertPosition { Before = anchor }, props); Type guard
static bool AnchorTargetsSheet(string anchorPath, string targetSheet)
{
var segs = anchorPath.TrimStart('/').Split('/', 2);
return segs.Length >= 2
&& segs[0].Equals(targetSheet, StringComparison.OrdinalIgnoreCase)
&& System.Text.RegularExpressions.Regex.IsMatch(segs[1], @"^col\[([A-Za-z]+)\]$", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
} Prevention
- Derive the anchor path from the same sheet variable used as the target sheet.
- Prefer position.Index (numeric) over Before/After when you already know the column number, to bypass anchor resolution entirely.
- Validate the anchor path format with the type guard before constructing the InsertPosition.
When it happens
Trigger: Calling Add with type=col on /TargetSheet and an InsertPosition whose Before or After is a path like /OtherSheet/col[C] where OtherSheet != TargetSheet. For example: parentPath="/Sheet1", position.Before="/Sheet2/col[B". The local function FindAnchorColIndex is only invoked when position.Index is null and Before/After is set.
Common situations: Script copies an anchor path from a different sheet's dump output and reuses it verbatim. Renaming a sheet after copying anchor paths. Mixing up sheet variables when building the position object across two sheets in the same script.
Related errors
- Invalid 'outline' value: '{addColOutline}'. Expected an inte
- Parent path must be /SheetName/CellRef for adding a run
- Sheet not found: {runSheetName}
- Sheet not found: {rbSheetName}
- 'row' property is required for rowbreak
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/41c1cf7275069124.
Report an issue: GitHub.