{"record":{"id":"c3e948b1b42bd0f1","repo":"iOfficeAI/OfficeCLI","slug":"sheet-not-found-sheetname-c3e948","errorCode":null,"errorMessage":"Sheet not found: {sheetName}","messagePattern":"Sheet not found: (.+?)","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Handlers/Excel/ExcelHandler.Add.cs","lineNumber":175,"sourceCode":"            case \"cfextended\":\n                return AddCfExtended(parentPath, type, position, properties);\n\n            case \"sparkline\":\n                return AddSparkline(parentPath, type, position, properties);\n\n            default:\n                return AddDefault(parentPath, type, position, properties);\n        }\n    }\n\n    public string Move(string sourcePath, string? targetParentPath, InsertPosition? position, Dictionary<string, string>? properties = null)\n    {\n        // xlsx has no track-change concept; `properties` is accepted for IDocumentHandler parity but ignored.\n        var index = position?.Index;\n        var segments = sourcePath.TrimStart('/').Split('/', 2);\n        var sheetName = segments[0];\n        var worksheet = FindWorksheet(sheetName)\n            ?? throw new ArgumentException($\"Sheet not found: {sheetName}\");\n\n        if (segments.Length < 2)\n        {\n            // Move (reorder) the sheet within the workbook.\n            // CONSISTENCY(move-anchor): mirrors PowerPointHandler.Move slide reorder —\n            // supports --index / --after /Sheet2 / --before /Sheet3.\n            var workbook = GetWorkbook();\n            var sheets = workbook.GetFirstChild<Sheets>()\n                ?? throw new InvalidOperationException(\"Workbook has no sheets element\");\n            var sheetEl = sheets.Elements<Sheet>().FirstOrDefault(s =>\n                string.Equals(s.Name?.Value, sheetName, StringComparison.OrdinalIgnoreCase))\n                ?? throw new ArgumentException($\"Sheet not found: {sheetName}\");\n\n            // Resolve after/before anchor BEFORE removing sheetEl.\n            static string ExtractAnchorSheetName(string raw) =>\n                (raw.StartsWith(\"/\") ? raw[1..] : raw).Split('/', 2)[0];\n\n            Sheet? afterAnchor = null, beforeAnchor = null;","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Handlers/Excel/ExcelHandler.Add.cs#L157-L193","documentation":"Thrown by ExcelHandler.Move at the very first step: FindWorksheet(sheetName) returned null, meaning the first segment of sourcePath does not name any worksheet in the workbook. The handler splits sourcePath on '/' and treats segment[0] as the sheet, so a missing sheet fails before any move logic runs. It is the standard 'you asked to move from a sheet that does not exist' guard.","triggerScenarios":"Calling Move(\"/Misnamed/row[3]\") where 'Misnamed' is not a worksheet; a leading slash/whitespace mismatch; calling Move on a path whose first segment is empty (e.g. sourcePath = \"/\"). Case-insensitive lookup is used for the later <sheets> catalog, but this first lookup still misses when the name is genuinely absent.","commonSituations":"Sheet renamed between sessions; copy-paste path with a stale sheet name; trailing spaces in the name; referencing a chart/dialog sheet that is not enumerated as a worksheet; operating on the wrong workbook instance.","solutions":["Enumerate sheets first (handler.Get(\"/\", depth:1) or the dump) and confirm the exact name before calling Move.","Trim and verify the first segment of sourcePath is non-empty and matches an existing sheet.","If the sheet was deleted/renamed, refresh the path from the current workbook."],"exampleFix":"// before\nh.Move(\"/Dat/row[2]\", \"/Report\", InsertPosition.AtIndex(0)); // typo: 'Dat'\n// after\nvar sheet = h.Get(\"/\", depth:1).Children.First(c => c.Name.Equals(\"Data\", StringComparison.OrdinalIgnoreCase));\nh.Move($\"/{sheet.Name}/row[2]\", \"/Report\", InsertPosition.AtIndex(0));","handlingStrategy":"validation","validationCode":"// Resolve the sheet segment exactly as Move does, then confirm it exists.\nvar firstSeg = sourcePath.AsSpan().TrimStart('/').ToString().Split('/', 2)[0];\nvar sheets = handler.Get(\"/\", depth: 1).Children\n    .Select(c => c.Name).ToList();\nif (!sheets.Any(s => s.Equals(firstSeg, StringComparison.OrdinalIgnoreCase)))\n    throw new InvalidOperationException($\"Refusing Move: sheet '{firstSeg}' not in {string.Join(\", \", sheets)}\");","typeGuard":"static bool IsSheetPath(string path) =>\n    !string.IsNullOrWhiteSpace(path)\n    && path.TrimStart('/').Split('/', 2)[0].Length > 0;","tryCatchPattern":"try { handler.Move(sourcePath, target, pos); }\ncatch (ArgumentException ex) when (ex.Message.StartsWith(\"Sheet not found\"))\n{ /* surface as a user-facing 'no such sheet' message; list available sheets */ }","preventionTips":["Always read the live sheet list from handler.Get(\"/\", depth:1) before constructing a move path.","Build paths from node.Name returned by Get/Query rather than hard-coded strings.","Trim and reject empty first segments before calling Move."],"tags":["excel","openxml","move","sheet-not-found","validation"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}