iOfficeAI/OfficeCLI · error · InvalidOperationException
Workbook has no sheets element
Error message
Workbook has no sheets element
What it means
Thrown during a whole-sheet reorder (sourcePath had no second segment) when workbook.GetFirstChild<Sheets>() is null. Every valid XLSX has a <sheets> catalog in xl/workbook.xml; its absence means the package is structurally corrupt or truncated, not that the user passed a bad argument. The move cannot proceed because the sheet catalog it must reorder does not exist.
Source
Thrown at src/officecli/Handlers/Excel/ExcelHandler.Add.cs:184
}
public string Move(string sourcePath, string? targetParentPath, InsertPosition? position, Dictionary<string, string>? properties = null)
{
// xlsx has no track-change concept; `properties` is accepted for IDocumentHandler parity but ignored.
var index = position?.Index;
var segments = sourcePath.TrimStart('/').Split('/', 2);
var sheetName = segments[0];
var worksheet = FindWorksheet(sheetName)
?? throw new ArgumentException($"Sheet not found: {sheetName}");
if (segments.Length < 2)
{
// Move (reorder) the sheet within the workbook.
// CONSISTENCY(move-anchor): mirrors PowerPointHandler.Move slide reorder —
// supports --index / --after /Sheet2 / --before /Sheet3.
var workbook = GetWorkbook();
var sheets = workbook.GetFirstChild<Sheets>()
?? throw new InvalidOperationException("Workbook has no sheets element");
var sheetEl = sheets.Elements<Sheet>().FirstOrDefault(s =>
string.Equals(s.Name?.Value, sheetName, StringComparison.OrdinalIgnoreCase))
?? throw new ArgumentException($"Sheet not found: {sheetName}");
// Resolve after/before anchor BEFORE removing sheetEl.
static string ExtractAnchorSheetName(string raw) =>
(raw.StartsWith("/") ? raw[1..] : raw).Split('/', 2)[0];
Sheet? afterAnchor = null, beforeAnchor = null;
if (position?.After != null)
{
var anchorName = ExtractAnchorSheetName(position.After);
afterAnchor = sheets.Elements<Sheet>().FirstOrDefault(s =>
string.Equals(s.Name?.Value, anchorName, StringComparison.OrdinalIgnoreCase))
?? throw new ArgumentException($"After anchor not found: {position.After}");
}
else if (position?.Before != null)
{View on GitHub (pinned to 1ced45e900)
Solutions
- Open and re-save the file in Excel/LibreOffice to regenerate workbook.xml, then retry.
- Validate the package with the Open XML SDK validator or an OOXML checker before handing it to the handler.
- If you produce the file programmatically, ensure Workbook.Sheets is created and at least one Sheet is registered.
Defensive patterns
Strategy: try-catch
Validate before calling
// Structural defect: cannot cheaply pre-validate from the public API. // Trust the throw; optionally validate the package out-of-band before opening.
Try / catch
try { handler.Move("/Sheet1", null, InsertPosition.AtIndex(0)); }
catch (InvalidOperationException ex) when (ex.Message == "Workbook has no sheets element")
{ /* file is corrupt: ask the user to re-save/repair the workbook */ } Prevention
- Validate OOXML packages with the SDK validator before processing.
- Re-save generated files in Excel/LibreOffice to normalize workbook.xml.
- Never copy an .xlsx while Excel holds it open/locked.
When it happens
Trigger: Operating on a hand-edited or partially-written .xlsx whose workbook.xml lost its <sheets> element; a file truncated during save/copy; a package produced by a non-conforming exporter that omits the sheets catalog.
Common situations: File copied while Excel still had it open/locked; generated by a broken export pipeline; corrupted download; a minimal package assembled without the sheets element.
Related errors
- Sheet not found: {sheetName}
- After anchor not found: {position.After}
- Before anchor not found: {position.Before}
- One of --index, --after, or --before is required when moving
- Sheet has no data
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/dba75428027ba47b.
Report an issue: GitHub.