{"record":{"id":"a3096b113b2543e9","repo":"iOfficeAI/OfficeCLI","slug":"sheet-not-found-sheetname-a3096b","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.DumpSupport.cs","lineNumber":62,"sourceCode":"        if (!string.IsNullOrEmpty(pkgProps.Category)) node.Format[\"category\"] = pkgProps.Category!;\n        return node;\n    }\n\n    /// <summary>\n    /// Enumerate every row of a sheet with ALL cells that carry content OR\n    /// style. The bulk Get path (GetSheetChildNodes) intentionally omits\n    /// styled-empty cells (&lt;c s=\"1\"/&gt;, issue #149 bloat guard); a dump\n    /// must include them because their xf holds user-visible formatting\n    /// (filled header bands, bordered empty grids). Each cell node is built\n    /// by the same CellToNode Get uses, so Format keys match Get exactly.\n    /// A dump-only <c>__raw</c> Format key carries the raw stored\n    /// &lt;x:v&gt; text so the emitter can reproduce numbers/dates without\n    /// going through display formatting.\n    /// </summary>\n    public List<DocumentNode> GetDumpRowNodes(string sheetName)\n    {\n        var worksheet = FindWorksheet(sheetName)\n            ?? throw new ArgumentException($\"Sheet not found: {sheetName}\");\n        var rows = new List<DocumentNode>();\n        var sheetData = GetSheet(worksheet).GetFirstChild<SheetData>();\n        if (sheetData == null) return rows;\n\n        // One evaluator per sheet: CellToNode lazily creates a fresh\n        // FormulaEvaluator per formula cell when none is passed, which is\n        // O(cells × sheet-size) on formula-heavy sheets.\n        var eval = new Core.FormulaEvaluator(sheetData, _doc.WorkbookPart);\n        // For unresolved-shared-string detection: a cell with t=\"s\" whose\n        // index has no entry (missing/truncated sharedStrings part) would\n        // otherwise surface its INDEX as the cell text — confidently-wrong\n        // data. Mark such cells so the emitter warns and skips them.\n        var sstCount = _doc.WorkbookPart?.SharedStringTablePart?.SharedStringTable?\n            .Elements<SharedStringItem>().Count() ?? 0;\n        var seenRowIndices = new HashSet<uint>();\n        foreach (var row in sheetData.Elements<Row>())\n        {\n            var ridx = row.RowIndex?.Value ?? 0;","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Handlers/Excel/ExcelHandler.DumpSupport.cs#L44-L80","documentation":"Thrown by GetDumpRowNodes(sheetName): it builds the per-row DocumentNode list for the dump emitter, enumerating cells (including styled-empty cells the bulk Get path omits) and evaluating formulas with one FormulaEvaluator per sheet. FindWorksheet returns null when no worksheet matches the (case-insensitive) name.","triggerScenarios":"Calling GetDumpRowNodes with a sheet name that does not exist — a typo, a sheet[N] token that did not resolve via the dump resolver, or a sheet removed after the dump started.","commonSituations":"Dump driver iterating a cached sheet list that went stale (sheet deleted mid-run); a hand-invoked dump with a wrong name; a sheet index that pointed past the end after reorder.","solutions":["Resolve the sheet name through the dump's own token resolver before calling.","Re-fetch the live sheet list and pass an exact name.","Guard the dump loop to skip/renotify on missing sheets instead of throwing."],"exampleFix":"// before\nvar nodes = handler.GetDumpRowNodes(\"SheetX\");\n// after — resolve against live sheets first\nvar live = handler.GetWorksheets().Select(w => w.Name).ToList();\nvar name = live.FirstOrDefault(n => n.Equals(\"SheetX\", StringComparison.OrdinalIgnoreCase));\nvar nodes = name != null ? handler.GetDumpRowNodes(name) : new List<DocumentNode>();","handlingStrategy":"validation","validationCode":"if (!handler.GetWorksheets().Any(w => w.Name.Equals(sheetName, StringComparison.OrdinalIgnoreCase)))\n    /* skip or reconcile before GetDumpRowNodes */","typeGuard":"static bool SheetResolves(ExcelHandler h, string sheetName) =>\n    h.GetWorksheets().Any(w => w.Name.Equals(sheetName, StringComparison.OrdinalIgnoreCase));","tryCatchPattern":"try { return handler.GetDumpRowNodes(sheetName); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"Sheet not found\"))\n{ return new List<DocumentNode>(); }","preventionTips":["Resolve sheet names against the live GetWorksheets() list before dumping.","Refresh the sheet set at dump start.","Guard the dump loop to skip deleted sheets."],"tags":["excel","openxml","dump","sheet-lookup"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}