jackwener/OpenCLI · error · CommandExecutionError

Mercury reimbursement-draft requires Browser Bridge uploadFi

Error message

Mercury reimbursement-draft requires Browser Bridge uploadFiles support to verify the intended receipt input

What it means

This CommandExecutionError is thrown by the mercury reimbursement-draft command when the browser automation `page` object does not expose an `uploadFiles` method. The command needs Browser Bridge's uploadFiles capability to attach the local receipt file to the expense form's hidden file input and verify the upload result. Without it, the command cannot safely proceed and fails fast before attempting the upload.

Source

Thrown at clis/mercury/reimbursement-draft.js:60

        const before = await inspectMercury(page);
        assertLoggedIn(before);

        await page.goto(MERCURY_EXPENSES_URL, { waitUntil: 'load', settleMs: 1500 });
        await page.wait({ time: 1 });
        const createSurface = await assertCreateExpenseSurface(page);
        if (createSurface.hasFinalSubmit && /review/i.test(createSurface.bodyPreview || '')) {
            throw new CommandExecutionError('Mercury appears to have an existing expense review open; refusing to click a possible final Submit expense button');
        }

        const opened = await clickCreateExpenseButton(page);
        if (!opened.clicked) {
            throw new CommandExecutionError('Could not find the Mercury Submit expense or New expense button');
        }

        await page.wait({ time: 2 });

        if (!page.uploadFiles) {
            throw new CommandExecutionError('Mercury reimbursement-draft requires Browser Bridge uploadFiles support to verify the intended receipt input');
        }
        const upload = await page.uploadFiles(RECEIPT_INPUT_SELECTOR, [input.receipt]);
        if (!upload || upload.uploaded !== true || upload.files !== 1) {
            throw new CommandExecutionError('Mercury receipt upload did not confirm exactly one uploaded file');
        }
        if (upload.target !== RECEIPT_INPUT_SELECTOR || upload.matches_n !== 1) {
            throw new CommandExecutionError('Mercury receipt upload did not confirm the intended receipt input');
        }
        const uploadedNames = Array.isArray(upload.file_names) ? upload.file_names : [];
        if (!uploadedNames.includes(receiptBasename(input.receipt))) {
            throw new CommandExecutionError('Mercury receipt upload did not confirm the expected receipt file');
        }

        if (input.ocrWaitSeconds > 0) await page.wait({ time: input.ocrWaitSeconds });

        const fields = await fillReimbursementFields(page, input);
        await page.wait({ time: 1 });
        const expectedFields = ['amount', 'currency', 'date', 'merchant', 'category', 'notes'];

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Update the Browser Bridge package to a version that implements `page.uploadFiles` (check for the method in the bridge changelog).
  2. Ensure the command is running with `browser: true` through the standard opencli Browser Bridge driver, not a custom page implementation.
  3. Verify the installed @jackwener/opencli and browser-bridge versions are compatible (npm ls / lockfile), then reinstall.
  4. If using a custom page shim, implement `uploadFiles(selector, files)` returning `{ uploaded, files, target, matches_n, file_names }`.

Example fix

// before (old bridge shim)
const page = createPageDriver({ goto, wait, evaluate });
// after
const page = createPageDriver({ goto, wait, evaluate, uploadFiles }); // Browser Bridge >= version with uploadFiles
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof page.uploadFiles !== 'function') {
  throw new Error('Browser driver lacks uploadFiles; update Browser Bridge');
}

Type guard

function supportsUploadFiles(page) {
  return typeof page?.uploadFiles === 'function';
}

Try / catch

try {
  await runReimbursementDraft(page, input);
} catch (e) {
  if (String(e.message).includes('uploadFiles support')) {
    // upgrade bridge or fall back to a driver that implements uploadFiles
  } else throw e;
}

Prevention

When it happens

Trigger: Running `opencli mercury reimbursement-draft --receipt ...` against a Browser Bridge / page driver whose API does not implement `uploadFiles` — e.g. an outdated browser-bridge package, a page handle obtained from a non-Bridge driver, or a bridge version where uploadFiles was renamed or not yet added.

Common situations: Developers hit this after upgrading opencli without upgrading the Browser Bridge dependency (or vice versa), when using an alternative driver (plain Puppeteer/Playwright wrapper) that lacks the Bridge extension, or when an old persistent site session reconnects to a stale bridge build.

Related errors


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