{"record":{"id":"ca5b897dcf32973b","repo":"iOfficeAI/OfficeCLI","slug":"workbook-is-a-singleton-use-workbook-or-no-in","errorCode":null,"errorMessage":"workbook is a singleton; use /workbook or / (no index).","messagePattern":"workbook is a singleton; use /workbook or / \\(no index\\)\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Handlers/Excel/ExcelHandler.Query.cs","lineNumber":227,"sourceCode":"                nrNode.Format[\"scope\"] = \"workbook\";\n            }\n            if (!string.IsNullOrEmpty(dn.Comment?.Value))\n                nrNode.Format[\"comment\"] = dn.Comment.Value;\n            if (dn.Function?.Value == true)\n                nrNode.Format[\"volatile\"] = true;\n\n            return nrNode;\n        }\n\n        // Parse path: /SheetName or /SheetName/A1 or /SheetName/A1:D10\n        var segments = path.TrimStart('/').Split('/', 2);\n        var sheetNameFromPath = segments[0];\n        // workbook is a singleton at the document root — reject an indexed\n        // /workbook[N] with a redirect rather than treating \"workbook[N]\" as a\n        // sheet name (which fires a misleading SheetNotFoundException). Mirrors\n        // the pptx notes[N]/theme[N] and docx watermark[N] redirects.\n        if (Regex.IsMatch(sheetNameFromPath, @\"^workbook\\[\\d+\\]$\", RegexOptions.IgnoreCase))\n            throw new ArgumentException(\"workbook is a singleton; use /workbook or / (no index).\");\n        // docProps is a document-level part, not a sheet — same redirect class.\n        if (Regex.IsMatch(sheetNameFromPath, @\"^docProps\\[\\d+\\]$\", RegexOptions.IgnoreCase))\n            throw new ArgumentException(\"docProps is a singleton; use /docProps or / (no index).\");\n        var worksheet = FindWorksheet(sheetNameFromPath);\n        if (worksheet == null)\n            throw SheetNotFoundException(sheetNameFromPath);\n        // CONSISTENCY(path-stability): if the path used sheet[N] / sheet[last()],\n        // rebuild the canonical path with the resolved sheet name so the returned\n        // node.Path reflects the actual sheet (matches Word's last() echo behavior).\n        var resolvedSheetName = ResolveSheetName(sheetNameFromPath);\n        if (!resolvedSheetName.Equals(sheetNameFromPath, StringComparison.Ordinal))\n        {\n            sheetNameFromPath = resolvedSheetName;\n            path = segments.Length == 1 ? $\"/{resolvedSheetName}\" : $\"/{resolvedSheetName}/{segments[1]}\";\n        }\n\n        var data = GetSheet(worksheet).GetFirstChild<SheetData>();\n        if (data == null)","sourceCodeStart":209,"sourceCodeEnd":245,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Handlers/Excel/ExcelHandler.Query.cs#L209-L245","documentation":"Thrown by ExcelHandler.Get when the first path segment matches /workbook[N] (an indexed form). The workbook is a singleton at the document root, so an index is meaningless; the guard redirects the caller to /workbook or / rather than treating 'workbook[N]' as a sheet name (which would fire a misleading SheetNotFoundException). Mirrors the same redirect class used for docProps[N], notes[N], theme[N].","triggerScenarios":"Issuing get /workbook[0], get /workbook[1], or programmatically calling Get(\"/workbook[2]\").","commonSituations":"An agent/loop that synthesizes indexed paths by template ('/{type}[{i}]'); a generic enumerator that assumes every top-level node is indexable; copy-paste of a sheet[N] pattern onto the workbook root.","solutions":["Address the workbook root without an index: use /workbook or simply /.","In generic enumerators, special-case the singleton roots (workbook, docProps) before emitting an indexed path."],"exampleFix":"// before\nget /workbook[0]\n\n// after\nget /\n// or\nget /workbook","handlingStrategy":"validation","validationCode":"if (Regex.IsMatch(path.TrimStart('/').Split('/',2)[0], @\"^workbook\\[\\d+\\]$\", RegexOptions.IgnoreCase))\n    path = \"/workbook\";   // normalize indexed singleton to its canonical root","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Address singleton roots (workbook, docProps) without an index.","In generic enumerators, special-case singleton segments before synthesizing indexed paths.","Do not apply the sheet[N] pattern to the workbook root."],"tags":["excel","validation","path","singleton","query"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}