nanocoai/nanoclaw · error
--${column.name.replace(/_/g, '-')} must be true or false
Error message
--${column.name.replace(/_/g, '-')} must be true or false What it means
Thrown by coerceListFilter in src/cli/crud.ts when a boolean column filter receives a value that is not one of true/false/'true'/'false'/'1'/'0'/1/0. The generic list handler coerces CLI filter flags into SQLite-storable 0/1 integers, and any other string (e.g. 'yes', 'on') is rejected. This protects boolean columns from being compared against non-boolean text.
Source
Thrown at src/cli/crud.ts:178
// ---------------------------------------------------------------------------
// Generic SQL handlers
// ---------------------------------------------------------------------------
function visibleColumns(def: ResourceDef): string[] {
return def.columns.map((c) => c.name);
}
function coerceListFilter(column: ColumnDef, value: unknown): unknown {
switch (column.type) {
case 'number': {
const number = Number(value);
if (Number.isNaN(number)) throw new Error(`--${column.name.replace(/_/g, '-')} must be a number`);
return number;
}
case 'boolean':
if (value === true || value === 'true' || value === '1' || value === 1) return 1;
if (value === false || value === 'false' || value === '0' || value === 0) return 0;
throw new Error(`--${column.name.replace(/_/g, '-')} must be true or false`);
case 'json':
return typeof value === 'string' ? value : JSON.stringify(value);
case 'string':
return String(value);
}
}
function listOrder(def: ResourceDef): string {
if (def.listOrder) return def.listOrder;
const timestamp = def.columns.find((column) => column.name.endsWith('_at'))?.name;
return timestamp ? `${timestamp} DESC, ${def.idColumn}` : def.idColumn;
}
function genericList(def: ResourceDef) {
const cols = visibleColumns(def).join(', ');
const filterableColumns = new Map(def.columns.filter((c) => !c.generated).map((c) => [c.name, c]));
return async (args: Record<string, unknown>) => {
const limit = args.limit !== undefined ? Math.max(1, Number(args.limit)) : 200;View on GitHub (pinned to 294ef2aee8)
Solutions
- Use exactly true or false (also accepted: 1/0, 'true'/'false')
- Check the column definition in src/cli/resources/<resource>.ts to confirm the column is actually boolean
- Quote the value in shells that mangle bare true/false
Example fix
# before ncl groups list --is-default yes # after ncl groups list --is-default true
Defensive patterns
Strategy: validation
Validate before calling
const BOOL_OK = new Set(['true','false','1','0',true,false,1,0]);
function assertBoolFlag(name: string, v: unknown) {
if (!BOOL_OK.has(v as any)) throw new Error(`${name} must be true or false`);
} Type guard
function isBoolFilter(v: unknown): boolean {
return [true,false,'true','false','1','0',1,0].includes(v as any);
} Prevention
- Normalize boolean CLI inputs to true/false before calling ncl
- Document accepted boolean spellings in wrapper scripts
When it happens
Trigger: Running `ncl <resource> list --<boolean-column> yes` or `--<boolean-column> on/off`, or any list filter where the resource defines a boolean column (e.g. is_default, enabled) and the caller passes an unrecognized truthiness spelling.
Common situations: Scripts assuming 'yes'/'no' or 'on'/'off' work as booleans; passing an empty string; passing 'True' with a capital T.
Related errors
- ${col.name} must be one of: ${col.enum.join(', ')}
- ${flag} must be true or false, got "${v}"
- Nothing to update — provide at least one of: --provider, --m
- --name is required
- --from and --to must differ (self-messages are never gated)
AI-assisted analysis of nanocoai/nanoclaw@294ef2aee8 (2026-08-28).
Data as JSON: /api/errors/42567196f2fa50b8.
Report an issue: GitHub.