{"record":{"id":"671f6cf5ba7dff91","repo":"iOfficeAI/OfficeCLI","slug":"anchor-must-be-a-col-path-like-sheetname-col-l","errorCode":null,"errorMessage":"Anchor must be a col path like /{sheetName}/col[L], got: {anchorPath}","messagePattern":"Anchor must be a col path like /(.+?)/col\\[L\\], got: (.+?)","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Handlers/Excel/ExcelHandler.Add.cs","lineNumber":435,"sourceCode":"        // anchor must be col[L] in same sheet).\n        var colMatch = Regex.Match(elementRef, @\"^col\\[([A-Za-z]+)\\]$\", RegexOptions.IgnoreCase);\n        if (colMatch.Success)\n        {\n            var srcColLetter = colMatch.Groups[1].Value.ToUpperInvariant();\n            var srcColIdx = ColumnNameToIndex(srcColLetter);\n\n            // Resolve target. Default behavior (no position): append after the\n            // last used column.\n            int? targetColIdx = null;\n            if (position?.Index.HasValue == true)\n                targetColIdx = position.Index!.Value;\n            else if (position?.Before != null || position?.After != null)\n            {\n                int FindAnchorColIdx(string anchorPath)\n                {\n                    var aSegs = anchorPath.TrimStart('/').Split('/', 2);\n                    if (aSegs.Length < 2)\n                        throw new ArgumentException(\n                            $\"Anchor must be a col path like /{sheetName}/col[L], got: {anchorPath}\");\n                    if (!aSegs[0].Equals(sheetName, StringComparison.OrdinalIgnoreCase))\n                        throw new ArgumentException(\n                            $\"Anchor sheet '{aSegs[0]}' must match source sheet '{sheetName}'\");\n                    var am = Regex.Match(aSegs[1], @\"^col\\[([A-Za-z]+)\\]$\", RegexOptions.IgnoreCase);\n                    if (!am.Success)\n                        throw new ArgumentException(\n                            $\"Anchor must be a col path like /{sheetName}/col[L], got: {anchorPath}\");\n                    return ColumnNameToIndex(am.Groups[1].Value.ToUpperInvariant());\n                }\n                if (position.Before != null) targetColIdx = FindAnchorColIdx(position.Before);\n                else targetColIdx = FindAnchorColIdx(position.After!) + 1;\n            }\n            else\n            {\n                // Append after last used column.\n                int maxCol = 1;\n                foreach (var r in sheetData.Elements<Row>())","sourceCodeStart":417,"sourceCodeEnd":453,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Handlers/Excel/ExcelHandler.Add.cs#L417-L453","documentation":"Thrown by the column-anchor resolver when a --before/--after anchor for a column move has no second segment (aSegs.Length < 2), i.e. the anchor is just \"/Sheet1\" with no '/col[L]'. Column anchors must be full element paths so the handler can map the letter to a column index.","triggerScenarios":"InsertPosition.BeforeElement(\"/Sheet1\") used for a column move; bare sheet name passed as anchor; '/col[L]' suffix omitted.","commonSituations":"Reusing a sheet-level anchor for a column move; truncation when constructing the path; confusing sheet-reorder anchors with element anchors.","solutions":["Provide the full anchor: \"/<sheet>/col[<L>]\" where L is a column letter (A, B, ...).","Derive anchors from a verified column path.","Use InsertPosition.AtIndex(n) with a numeric column index instead."],"exampleFix":"// before\nh.Move(\"/Sheet1/col[A]\", null, InsertPosition.AfterElement(\"/Sheet1\")); // no col segment\n// after\nh.Move(\"/Sheet1/col[A]\", null, InsertPosition.AfterElement(\"/Sheet1/col[C]\"));","handlingStrategy":"validation","validationCode":"string AssertColAnchor(string anchor)\n{\n    var segs = anchor.TrimStart('/').Split('/', 2);\n    if (segs.Length < 2)\n        throw new ArgumentException($\"Column anchor needs /sheet/col[L] form: '{anchor}'\");\n    return anchor;\n}\nvar after = pos?.After is null ? null : AssertColAnchor(pos.After);\nvar before = pos?.Before is null ? null : AssertColAnchor(pos.Before);","typeGuard":"static bool IsFullElementPath(string p) =>\n    p.TrimStart('/').Split('/', 2).Length >= 2;","tryCatchPattern":null,"preventionTips":["Always include the /col[L] suffix on column anchors.","Build anchors from a verified column path.","Prefer AtIndex(n) for absolute column positions."],"tags":["excel","openxml","move","col-move","anchor","malformed-path"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}