jackwener/OpenCLI · error · CommandExecutionError

Mercury returned malformed ${label}: ${field} must be boolea

Error message

Mercury returned malformed ${label}: ${field} must be boolean

What it means

assertBooleanFields walks a list of expected fields on a Mercury state object and requires each to be strictly boolean. Any field that is undefined, null, a string ('true'), or a number throws CommandExecutionError 'Mercury returned malformed <label>: <field> must be boolean'. It protects flag-style fields (e.g. logged-in/loading indicators) from ambiguous truthy values.

Source

Thrown at clis/mercury/utils.js:125

export function assertObject(value, label) {
    if (!value || typeof value !== 'object' || Array.isArray(value)) {
        throw new CommandExecutionError(`Mercury returned malformed ${label}`);
    }
    return value;
}

export function assertMercuryState(value, label = 'page state') {
    const state = assertObject(value, label);
    if (typeof state.url !== 'string' || typeof state.title !== 'string') {
        throw new CommandExecutionError(`Mercury returned malformed ${label}`);
    }
    return state;
}

function assertBooleanFields(state, label, fields) {
    for (const field of fields) {
        if (typeof state[field] !== 'boolean') {
            throw new CommandExecutionError(`Mercury returned malformed ${label}: ${field} must be boolean`);
        }
    }
    return state;
}

export async function inspectMercury(page) {
    await page.goto(MERCURY_EXPENSES_URL, { waitUntil: 'load', settleMs: 1500 });
    await page.wait({ time: 1 });

    const state = await page.evaluate(`(() => {
        const text = document.body?.innerText || '';
        const url = location.href;
        return {
            url,
            loggedIn: !/\\/login\\b/.test(url) && !/sign in|log in|password|passkey/i.test(text),
            hasSubmitExpense: /Submit expense/i.test(text),
            hasReimbursements: /Reimbursements|My Expenses|Submitted Expenses/i.test(text),
            title: document.title

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Identify the offending field from the error message and log the raw Mercury payload to confirm its type.
  2. Update or downgrade the Mercury extension/CLI so both sides agree the field is a real boolean.
  3. If values arrive as strings, coerce explicitly before validation: state[f] = state[f] === 'true'.
  4. Ensure any proxy/middleware between Mercury and the CLI preserves JSON boolean types (no template-string rebuilding).

Example fix

// before
const state = JSON.parse(await redis.get('mercury-state')); // booleans stringified by writer
// after
const state = JSON.parse(await redis.get('mercury-state'));
for (const f of ['loggedIn', 'ready']) if (typeof state[f] === 'string') state[f] = state[f] === 'true';
assertBooleanFields(state, 'page state', ['loggedIn', 'ready']);
Defensive patterns

Strategy: type-guard

Validate before calling

function hasBooleanFields(v, fields) {
  return v !== null && typeof v === 'object' && fields.every(f => typeof v[f] === 'boolean');
}

Type guard

function isMercuryStateWithFlags(v, fields) {
  return typeof v === 'object' && v !== null && !Array.isArray(v)
    && fields.every(f => typeof v[f] === 'boolean');
}

Try / catch

try {
  const state = await inspectMercury(page);
} catch (e) {
  if (e instanceof CommandExecutionError && e.message.includes('must be boolean')) {
    const field = /: (\w+) must be boolean/.exec(e.message)?.[1];
    console.error(`Mercury flag field '${field}' has wrong type; check extension/CLI version match`);
  } else throw e;
}

Prevention

When it happens

Trigger: Mercury state missing one of the required boolean fields; field serialized as string 'true'/'false' by an older/newer Mercury version; field present but null; payload passed through a transformation that coerced booleans to 0/1.

Common situations: Version drift between Mercury extension and CLI changing field types; JSON produced by a custom proxy/serializer that stringifies booleans; partially-failed page snapshots omitting fields; middleware logging layers rebuilding state objects.

Understand the failure class

Related errors


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