{"record":{"id":"754d93ca99b2a133","repo":"iOfficeAI/OfficeCLI","slug":"row-rowidx-not-found","errorCode":null,"errorMessage":"Row {rowIdx} not found","messagePattern":"Row (.+?) not found","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Handlers/Excel/ExcelHandler.Add.cs","lineNumber":301,"sourceCode":"        else\n        {\n            var tgtSegments = targetParentPath.TrimStart('/').Split('/', 2);\n            var tgtWorksheet = FindWorksheet(tgtSegments[0])\n                ?? throw new ArgumentException($\"Target sheet not found: {tgtSegments[0]}\");\n            targetSheetData = GetSheet(tgtWorksheet).GetFirstChild<SheetData>()\n                ?? throw new ArgumentException(\"Target sheet has no data\");\n        }\n\n        // Find and move the row\n        var rowMatch = Regex.Match(elementRef, @\"^row\\[(\\d+)\\]$\");\n        if (rowMatch.Success)\n        {\n            var rowIdx = int.Parse(rowMatch.Groups[1].Value);\n            // Try ordinal lookup first (Nth row element), then fall back to RowIndex\n            var allRows = sheetData.Elements<Row>().ToList();\n            var row = (rowIdx >= 1 && rowIdx <= allRows.Count ? allRows[PathIndex.ToArrayIndex(rowIdx)] : null)\n                ?? sheetData.Elements<Row>().FirstOrDefault(r => r.RowIndex?.Value == (uint)rowIdx)\n                ?? throw new ArgumentException($\"Row {rowIdx} not found\");\n\n            // Resolve --before / --after anchors to a 0-based document-order\n            // position in the target sheet. Anchor must be /<TargetSheet>/row[K].\n            // Resolved BEFORE removing the moved row so the anchor is found by\n            // its current position.\n            int? targetIndex = index;\n            string targetSheetName = string.IsNullOrEmpty(targetParentPath)\n                ? sheetName\n                : targetParentPath.TrimStart('/').Split('/', 2)[0];\n            if (targetIndex == null && position != null && (position.After != null || position.Before != null))\n            {\n                int FindAnchorRowPos(string anchorPath)\n                {\n                    var aSegs = anchorPath.TrimStart('/').Split('/', 2);\n                    if (aSegs.Length < 2)\n                        throw new ArgumentException(\n                            $\"Anchor must be a row path like /{targetSheetName}/row[K], got: {anchorPath}\");\n                    if (!aSegs[0].Equals(targetSheetName, StringComparison.OrdinalIgnoreCase))","sourceCodeStart":283,"sourceCodeEnd":319,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Handlers/Excel/ExcelHandler.Add.cs#L283-L319","documentation":"Thrown during a row move when row[N] does not resolve: it is out of ordinal range (N > row count) AND no <Row> element has RowIndex == N. Lookup tries ordinal (Nth row element) then falls back to matching the stored RowIndex, so a genuinely absent row fails.","triggerScenarios":"Move(\"/Sheet1/row[999]\") when the sheet has fewer rows; referencing a row index that was deleted; 1-based confusion where the user expected a sparse row that is not stored.","commonSituations":"Off-by-one on the 1-based index; row removed in a prior edit; assuming every row up to the used range is materialized (Excel omits empty rows).","solutions":["Query the sheet's actual rows first (handler.Get(\"/Sheet1\")) to see which indices exist.","Use the ordinal count, not the spreadsheet's visual row number, when picking N.","If the row is genuinely missing, insert it (Add row) before moving."],"exampleFix":"// before\nh.Move(\"/Sheet1/row[50]\", null, null); // only 10 rows stored -> throws\n// after\nvar rows = h.Get(\"/Sheet1\", depth:2).Children.Where(c => c.Type == \"row\").ToList();\nh.Move($\"/Sheet1/row[{rows.Count}]\", null, InsertPosition.AtIndex(1)); // move last real row","handlingStrategy":"validation","validationCode":"// Confirm the requested row index is actually stored.\nvar m = System.Text.RegularExpressions.Regex.Match(elementRef, @\"^row\\[(\\d+)\\]$\");\nvar rowIdx = int.Parse(m.Groups[1].Value);\nvar rows = handler.Get(sheetName, depth: 2).Children.Where(c => c.Type == \"row\").ToList();\nif (rowIdx < 1 || rowIdx > rows.Count) // ordinal check mirrors the handler's first attempt\n    throw new InvalidOperationException($\"Row {rowIdx} not present (have {rows.Count} rows)\");","typeGuard":"static bool IsRowIndex(int n, int rowCount) => n >= 1 && n <= rowCount;","tryCatchPattern":"try { handler.Move($\"/{sheet}/row[{n}]\", target, pos); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"not found\"))\n{ /* enumerate real rows and retry with a valid index */ }","preventionTips":["Use the stored row count (ordinal), not the spreadsheet's visual row number.","Enumerate rows via Get(sheet, depth:2) before choosing N.","Remember Excel omits empty rows; not every index is materialized."],"tags":["excel","openxml","move","row-move","not-found","off-by-one"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}