jackwener/OpenCLI · error · ArgumentError
Argument "${argDef.name}" must be a boolean (true/false). Re
Error message
Argument "${argDef.name}" must be a boolean (true/false). Received: "${val}" What it means
For arguments typed 'boolean'/'bool', coerceAndValidateArgs accepts true/false (case-insensitive) and '1'/'0' strings; numeric/other types are coerced with Boolean(). A string that is not one of true/false/1/0 (case-insensitive) throws ArgumentError requiring a boolean value.
Source
Thrown at src/execution.ts:82
);
}
if (val !== undefined && val !== null) {
if (argDef.type === 'int' || argDef.type === 'number') {
const num = Number(val);
if (!Number.isFinite(num)) {
throw new ArgumentError(`Argument "${argDef.name}" must be a valid number. Received: "${val}"`);
}
if (argDef.type === 'int' && !Number.isInteger(num)) {
throw new ArgumentError(`Argument "${argDef.name}" must be a valid integer. Received: "${val}"`);
}
result[argDef.name] = num;
} else if (argDef.type === 'boolean' || argDef.type === 'bool') {
if (typeof val === 'string') {
const lower = val.toLowerCase();
if (lower === 'true' || lower === '1') result[argDef.name] = true;
else if (lower === 'false' || lower === '0') result[argDef.name] = false;
else throw new ArgumentError(`Argument "${argDef.name}" must be a boolean (true/false). Received: "${val}"`);
} else {
result[argDef.name] = Boolean(val);
}
}
const coercedVal = result[argDef.name];
if (argDef.choices && argDef.choices.length > 0) {
if (!argDef.choices.map(String).includes(String(coercedVal))) {
throw new ArgumentError(`Argument "${argDef.name}" must be one of: ${argDef.choices.join(', ')}. Received: "${coercedVal}"`);
}
}
} else if (argDef.default !== undefined) {
result[argDef.name] = argDef.default;
}
}
return result;
}
View on GitHub (pinned to 49907e53dc)
Solutions
- Use true/false (or 1/0), e.g. --headless true.
- Map yes/no or on/off to true/false in the calling script before passing.
- In programmatic use, pass actual booleans rather than strings.
- Check the argument's declared type; if it should accept more forms, update the arg definition (library-side).
Example fix
// before opencli run --headless yes // after opencli run --headless true
Defensive patterns
Strategy: validation
Validate before calling
function toBool(v: unknown): boolean {
if (typeof v === 'boolean') return v;
const s = String(v).toLowerCase();
if (s === 'true' || s === '1') return true;
if (s === 'false' || s === '0') return false;
throw new Error(`Expected boolean (true/false/1/0), got: ${String(v)}`);
}
kwargs.headless = toBool(kwargs.headless); Type guard
const isBooleanLike = (v: unknown): v is boolean | 'true' | 'false' | '1' | '0' => typeof v === 'boolean' || ['true', 'false', '1', '0'].includes(String(v).toLowerCase());
Try / catch
try {
await opencli.run(cmd, kwargs);
} catch (e) {
if (/must be a boolean/.test(e.message)) {
console.error(`${e.message} — map yes/no or on/off to true/false first.`);
} else throw e;
} Prevention
- Use true/false (or 1/0) instead of yes/no, on/off, Y/N.
- Pass real booleans, not strings, in programmatic kwargs.
- Normalize boolean-like input at the script boundary before invoking the CLI.
When it happens
Trigger: Passing --headless yes, --debug on, --enabled TRUE-ish variants outside the accepted set (e.g. 'y', 't'), or kwargs like { dryRun: 'maybe' } to a bool-typed argument.
Common situations: Shell conventions using yes/no or on/off; interactive prompts feeding 'Y'/'N'; config files with boolean-like strings other than the accepted four.
Related errors
- Argument "${argDef.name}" must be a valid number. Received:
- Argument "${argDef.name}" must be a valid integer. Received:
- Not a git repository
- Working tree not clean: ${status}
- Stale .git/index.lock found — remove it first
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/6783fd4b3836fb77.
Report an issue: GitHub.