jackwener/OpenCLI · error · ArgumentError

Boolean argument ${name} must be true or false

Error message

Boolean argument ${name} must be true or false

What it means

optionalBoolean parses a boolean argument leniently: real booleans pass through, strings like 'true'/'yes'/'1'/'on' become true, 'false'/'no'/'0'/'off' become false, and anything else falls back to the default. If the value is a string but not in either accepted list, it throws ArgumentError telling the caller the argument must be true or false.

Source

Thrown at clis/mercury/utils.js:29

        throw new ArgumentError(`Missing required argument: ${name}`);
    }
    return value.trim();
}

export function optionalString(kwargs, name, fallback) {
    const value = kwargs[name];
    if (typeof value !== 'string' || value.trim() === '') return fallback;
    return value.trim();
}

export function optionalBoolean(kwargs, name, fallback = false) {
    const value = kwargs[name];
    if (typeof value === 'boolean') return value;
    if (typeof value === 'string') {
        const normalized = value.trim().toLowerCase();
        if (['1', 'true', 'yes', 'y', 'on'].includes(normalized)) return true;
        if (['0', 'false', 'no', 'n', 'off'].includes(normalized)) return false;
        throw new ArgumentError(`Boolean argument ${name} must be true or false`);
    }
    return fallback;
}

function parseReceiptPath(kwargs) {
    const receipt = path.resolve(requireString(kwargs, 'receipt'));
    let stat;
    try {
        stat = fs.statSync(receipt, { throwIfNoEntry: false });
    }
    catch (error) {
        throw new ArgumentError(`Receipt file cannot be read: ${receipt}`, error instanceof Error ? error.message : undefined);
    }
    if (!stat || !stat.isFile()) {
        throw new ArgumentError(`Receipt file does not exist: ${receipt}`);
    }
    return receipt;
}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Change the value to one of the accepted strings: 1, true, yes, y, on, 0, false, no, n, off (case-insensitive).
  2. Prefer passing a real boolean (true/false) instead of a string when calling programmatically.
  3. Omit the argument entirely if you want the default — optionalBoolean returns the fallback for undefined values.
  4. Update wrapper scripts/configs to emit canonical boolean strings.

Example fix

// before
await draftReimbursement({ receipt: 'r.pdf', amount: '10', date: '2026-08-29', closeAfterReview: 'enabled' });
// after
await draftReimbursement({ receipt: 'r.pdf', amount: '10', date: '2026-08-29', closeAfterReview: 'true' });
Defensive patterns

Strategy: validation

Validate before calling

const BOOL_TRUE = ['1','true','yes','y','on'];
const BOOL_FALSE = ['0','false','no','n','off'];
function checkBoolArg(kwargs, name) {
    const v = kwargs[name];
    if (v === undefined || typeof v === 'boolean') return;
    if (typeof v === 'string') {
        const n = v.trim().toLowerCase();
        if (BOOL_TRUE.includes(n) || BOOL_FALSE.includes(n)) return;
    }
    throw new Error(`Boolean argument ${name} must be true or false`);
}
checkBoolArg(input, 'closeAfterReview');

Type guard

function isBoolLike(v) {
    if (typeof v === 'boolean' || v === undefined) return true;
    if (typeof v !== 'string') return false;
    const n = v.trim().toLowerCase();
    return ['1','true','yes','y','on','0','false','no','n','off'].includes(n);
}

Try / catch

try {
    await draftReimbursement(input);
} catch (err) {
    if (err instanceof ArgumentError && err.message.includes('must be true or false')) {
        console.error('Invalid boolean value; use true/false (also: 1/0, yes/no, on/off)');
        process.exitCode = 2;
        return;
    }
    throw err;
}

Prevention

When it happens

Trigger: Calling normalizeReimbursementInput with a boolean-ish argument (e.g. closeAfterReview) whose string value is not one of 1/true/yes/y/on/0/false/no/n/off — e.g. 'maybe', 'enabled', '2', or 't' throws; casing is normalized so 'TRUE' is fine.

Common situations: Config file uses 'enabled'/'disabled' instead of the accepted tokens; user passes an unlisted variant like 'yeah'; a wrapper converts booleans to unexpected words; localized flag values in scripts.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/c906a51cb4d725db. Report an issue: GitHub.