jackwener/OpenCLI · error · CommandExecutionError

Mercury Review button was not clicked; inspect the page for

Error message

Mercury Review button was not clicked; inspect the page for validation errors

What it means

After clicking the 'Review' button via the in-page script, the automation checks the returned `clicked` flag. Mercury itself reports that no element matching the 'Review' label was found or clicked (the script returns `{ clicked: false }`). The error tells the developer to look at the rendered page — usually a form validation error is blocking progression to the Review step.

Source

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

        }

        const reviewClick = await page.evaluate(`(() => {
            const norm = (s) => String(s || '').replace(/\\s+/g, ' ').trim().toLowerCase();
            const candidates = Array.from(document.querySelectorAll('button, a, [role="button"], [role="link"]'))
              .filter((node) => {
                const style = window.getComputedStyle(node);
                return style.visibility !== 'hidden' && style.display !== 'none' && node.offsetParent !== null;
              });
            const el = candidates.find((node) => norm(node.innerText || node.textContent || '') === 'review');
            if (!el) return { clicked: false };
            el.click();
            return { clicked: true, text: el.innerText || el.textContent || '' };
        })()`);
        if (!reviewClick || typeof reviewClick !== 'object' || typeof reviewClick.clicked !== 'boolean') {
            throw new CommandExecutionError('Mercury returned malformed Review click result');
        }
        if (!reviewClick.clicked) {
            throw new CommandExecutionError('Mercury Review button was not clicked; inspect the page for validation errors');
        }
        await page.wait({ time: 2 });
        const review = await reviewSnapshot(page);
        if (!review.hasReview || !review.hasSubmitExpenseButton) {
            throw new CommandExecutionError('Mercury did not reach the Review step with the final Submit expense button visible');
        }

        if (input.closeAfterReview) {
            await page.evaluate(`(() => {
                const norm = (s) => String(s || '').replace(/\\s+/g, ' ').trim().toLowerCase();
                const el = Array.from(document.querySelectorAll('button, a, [role="button"], [role="link"]'))
                  .find((node) => norm(node.innerText || node.textContent || '') === 'close');
                el?.click();
                return { clicked: Boolean(el) };
            })()`);
            await page.wait({ time: 1 });
        }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Inspect the Mercury page for form validation errors and fix the underlying input (amount, date, receipt, merchant).
  2. Re-run with the page fully loaded; a partially rendered SPA may not expose the Review button yet.
  3. Check whether Mercury changed the button label/markup; update the text-match ('review') in reimbursement-draft.js if so.
  4. Capture a screenshot or page snapshot at failure time to confirm what state the form is in.

Example fix

// before
throw new CommandExecutionError('Mercury Review button was not clicked; inspect the page for validation errors');
// after
const snapshot = await page.evaluate(`document.body.innerText.slice(0, 2000)`);
throw new CommandExecutionError(`Mercury Review button was not clicked; page state: ${snapshot}`);
Defensive patterns

Strategy: validation

Validate before calling

// before invoking, confirm the form is fully rendered and no validation errors are visible
const ready = await page.evaluate(`(() => {
    const norm = (s) => String(s || '').replace(/\\s+/g, ' ').trim().toLowerCase();
    return Array.from(document.querySelectorAll('button, a, [role=button], [role=link]'))
        .some((n) => norm(n.innerText || n.textContent || '') === 'review');
})()`);
if (!ready) throw new Error('Review button not present; fix form validation first');

Type guard

function canClickReview(snapshot) { return snapshot.ready === true && snapshot.validationErrors.length === 0; }

Try / catch

try {
    await draftReimbursement(input);
} catch (err) {
    if (err.message.includes('Review button was not clicked')) {
        const pageText = await page.evaluate('document.body.innerText');
        throw new Error(`Form blocked Review: ${pageText.slice(0, 500)}`);
    }
    throw err;
}

Prevention

When it happens

Trigger: The in-page script found no clickable element whose normalized innerText equals 'review' (candidates.find returned undefined), so it returned `{ clicked: false }` and this error was thrown.

Common situations: Mercury form has field-level validation errors (bad amount, missing receipt/date) that hide or disable the Review button; Mercury UI redesign changed the button label from 'Review'; the page is stuck on an earlier step or showing an error banner.

Related errors


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