{"record":{"id":"b8cd3532d5de7f4e","repo":"iOfficeAI/OfficeCLI","slug":"invalid-selector-b8cd35","errorCode":"invalid_selector","errorMessage":"Wildcard sheet scope ('*/row[...]') is not supported — omit the sheet prefix entirely; an unscoped row[...] searches every sheet.","messagePattern":"Wildcard sheet scope \\('\\*/row\\[\\.\\.\\.\\]'\\) is not supported — omit the sheet prefix entirely; an unscoped row\\[\\.\\.\\.\\] searches every sheet\\.","errorType":"exception","errorClass":"CliException","httpStatus":null,"severity":"error","filePath":"src/officecli/Handlers/Excel/ExcelHandler.Query.RowWhere.cs","lineNumber":70,"sourceCode":"        var m = Regex.Match(key, @\"^col(?:umn)?\\.(.+)$\", RegexOptions.IgnoreCase);\n        return m.Success ? m.Groups[1].Value : key;\n    }\n\n\n    // Match table data rows whose cells satisfy every column predicate. Auto-\n    // binds to the single ListObject that owns all referenced columns; throws on\n    // no-match or cross-table ambiguity rather than silently picking one.\n    private List<DocumentNode> QueryRowsByColumnPredicate(string? sheetFilter, AttributeFilter.FilterExpr expr)\n    {\n        // Distinct leaf predicates drive column resolution and probe building; the\n        // expression tree (which may be `or` / parens, e.g. row[金额>5 or 金额<1])\n        // drives the actual row match via MatchesExpr.\n        var colConds = AttributeFilter.LeafConditions(expr).ToList();\n        // `*/row[...]` reads as a literal sheet named \"*\" and would report the\n        // baffling \"no table on sheet '*'\". Wildcard sheet scope is not a\n        // thing — the UNSCOPED form already searches every sheet.\n        if (sheetFilter == \"*\")\n            throw new Core.CliException(\n                \"Wildcard sheet scope ('*/row[...]') is not supported — omit the sheet prefix entirely; \" +\n                \"an unscoped row[...] searches every sheet.\")\n            { Code = \"invalid_selector\", Suggestion = \"row[...] (no sheet prefix) searches all sheets\" };\n        // A table that owns every referenced column. ListObjects are\n        // authoritative (column names are stored metadata); detected tables are\n        // a header-sniff heuristic (stable=false), so they are only consulted\n        // when no ListObject matches — a real table never loses to a guess.\n        var listObjCands = new List<(string sheetName, WorksheetPart part, string label, string source,\n            int dataR1, int dataR2, Dictionary<string, int> colAbsIndex)>();\n        var detectedCands = new List<(string sheetName, WorksheetPart part, string label, string source,\n            int dataR1, int dataR2, Dictionary<string, int> colAbsIndex)>();\n        // Every table in scope with its header names — used only to build a\n        // helpful \"no such column\" error (list all when few, suggest similar\n        // when many). Collected regardless of whether a table resolves the\n        // predicate, so a typo'd column still surfaces the real names.\n        var scopeTables = new List<(string label, List<string> cols)>();\n\n        foreach (var (sheetName, worksheetPart) in GetWorksheets())","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Handlers/Excel/ExcelHandler.Query.RowWhere.cs#L52-L88","documentation":"Thrown by QueryRowsByColumnPredicate when the row[...] selector is scoped with a literal '*' sheet (e.g. '*/row[Salary>5]'). Wildcard sheet scope is not a feature; the unscoped form row[...] already searches every sheet, so the '*' would otherwise be read as a literal sheet named '*' and produce a baffling 'no table on sheet' error.","triggerScenarios":"Issuing a selector like '/*/row[Amount>100]' or passing sheetFilter=\"*\" to the underlying query API.","commonSituations":"An LLM or user trained on glob/SQL wildcards assuming '*' means 'all sheets'; transposing the CSS/XPath wildcard habit onto the path grammar.","solutions":["Omit the sheet prefix entirely: use 'row[Amount>100]' so the query searches every sheet.","To restrict to one sheet, use its explicit name: '/SheetName/row[Amount>100]'."],"exampleFix":"// before\n/Sheet1/*/row[Amount>100]\n*/row[Status='open']\n\n// after\nrow[Amount>100]            // searches every sheet\n/Sheet1/row[Status='open'] // restricted to one sheet","handlingStrategy":"validation","validationCode":"if (sheetFilter == \"*\")\n    throw new ArgumentException(\"Wildcard sheet scope is unsupported; use row[...] without a sheet prefix.\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Drop the sheet prefix to search every sheet; never use '*' as a sheet scope.","Use an explicit sheet name when you need to restrict scope.","Validate selector strings against the documented path grammar before dispatch."],"tags":["excel","selector","row-where","validation"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}