iOfficeAI/OfficeCLI · error · CliException
not_found
not_found
Error message
row[col op val] found no usable table on {scope}: a header '{h.name}' exists at {h.sheet}!{h.cellRef}, but the surrounding cells are not a recognizable table. Auto-detection needs at least 2 adjacent non-empty header columns and at least 1 data row; a blank-header column in the middle or a header-only block breaks it. Create the table explicitly (add <file> /{h.sheet} --type table --prop ref=<A1:D10>), or address cells directly. What it means
Thrown by QueryRowsByColumnPredicate when no recognizable table was found in scope, but the predicate's column name DOES exist as a bare cell. This means the data is not structured as a detectable table: auto-detection requires at least 2 adjacent non-empty header columns and at least 1 data row. A blank-header gap column or a header-only block breaks detection.
Source
Thrown at src/officecli/Handlers/Excel/ExcelHandler.Query.RowWhere.cs:145
}
var candidates = listObjCands.Count > 0 ? listObjCands : detectedCands;
if (candidates.Count == 0)
{
var cols = string.Join(", ", colConds.Select(c => $"'{StripColPrefix(c.Key)}'"));
var scope = sheetFilter == null ? "any sheet" : $"sheet '{sheetFilter}'";
// If NO table structure exists in scope at all, but the column NAME
// literally exists as a cell, the honest cause is "not a recognizable
// table" (a blank-header gap column, or a header-only block with no
// data rows) — point at explicit table creation. Guard on an empty
// scopeTables: when a real table WAS detected but simply doesn't own
// one of a compound predicate's columns (`row[Region=X and Bonus>1]`
// where Bonus is absent), fall through to BuildNoColumnException so
// the error names the missing column and lists the available ones,
// instead of wrongly blaming a valid column's surrounding cells.
if (scopeTables.Count == 0 && FindHeaderLikeCell(sheetFilter, colConds) is {} h)
throw new Core.CliException(
$"row[col op val] found no usable table on {scope}: a header '{h.name}' exists at " +
$"{h.sheet}!{h.cellRef}, but the surrounding cells are not a recognizable table. " +
"Auto-detection needs at least 2 adjacent non-empty header columns and at least 1 data " +
"row; a blank-header column in the middle or a header-only block breaks it. Create the " +
$"table explicitly (add <file> /{h.sheet} --type table --prop ref=<A1:D10>), or address cells directly.")
{
Code = "not_found",
Suggestion = $"add <file> /{h.sheet} --type table --prop ref=<range covering the header and data>",
};
throw BuildNoColumnException(
$"row[col op val] found no table on {scope} with column(s) {cols}. " +
"Column predicates resolve header names (or column letters) against a ListObject or a detected (header-row) table.",
scopeTables, colConds);
}
if (candidates.Count > 1)
{
var where = string.Join(", ", candidates.Select(c => $"{c.sheetName}!{c.label}"));
var sheets = candidates.Select(c => c.sheetName).Distinct().ToList();View on GitHub (pinned to 1ced45e900)
Solutions
- Create the table explicitly so column names are stored metadata: add <file> /SheetName --type table --prop ref=<A1:D10> covering the header and data rows.
- If the layout is correct but detection is being defeated by a blank header, fill the blank header or remove the gap column.
- If you only need cells, address them directly (e.g. /Sheet1/B2) instead of using row[...].
Example fix
// before (header 'Region' sits alone or next to a blank cell) get /Sheet1/row[Region='West'] // after (declare the table range explicitly) add /file.xlsx /Sheet1 --type table --prop ref=A1:D100 get /Sheet1/row[Region='West']
Defensive patterns
Strategy: validation
Validate before calling
// Ensure the target range is a real ListObject before relying on row[...].
bool HasTableCovering(ExcelHandler excel, string sheet, string rangeRef)
=> excel.Get($"/{sheet}").Children.Any(c => c.Type == "table" && (c.Format.TryGetValue("ref", out var r) && r?.ToString() == rangeRef)); Try / catch
try { var rows = excel.QueryRowsByColumnPredicate(sheet, expr); }
catch (Core.CliException ex) when (ex.Code == "not_found" && ex.Message.Contains("not a recognizable table"))
{ /* prompt user to add --type table with an explicit ref */ } Prevention
- Declare tables explicitly (add --type table --prop ref=A1:D100) rather than relying on header-sniff detection.
- Ensure header rows have no blank gap columns and at least one data row.
- Address cells directly when the data is not tabular.
When it happens
Trigger: Running row[Region=X] against a sheet where 'Region' is a single header cell with no adjacent populated headers, or where a blank column splits the header row, or where headers exist but there are no data rows beneath them.
Common situations: Importing a CSV whose first column header is blank; pasting a header-only block; a header row interrupted by a merged/empty cell; data laid out as a key/value block instead of a tabular table.
Related errors
- Property 'sqref' (or 'range'/'ref') is required for validati
- invalid_selector
- invalid_value
- unsupported_type
- number format is {formatCode.Length} chars; Excel's limit is
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/9dd9aefcbd7c0a34.
Report an issue: GitHub.