{"record":{"id":"48418df1d1afca70","repo":"jackwener/OpenCLI","slug":"mercury-review-button-was-not-clicked-inspect-the","errorCode":null,"errorMessage":"Mercury Review button was not clicked; inspect the page for validation errors","messagePattern":"Mercury Review button was not clicked; inspect the page for validation errors","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/mercury/reimbursement-draft.js","lineNumber":100,"sourceCode":"        }\n\n        const reviewClick = await page.evaluate(`(() => {\n            const norm = (s) => String(s || '').replace(/\\\\s+/g, ' ').trim().toLowerCase();\n            const candidates = Array.from(document.querySelectorAll('button, a, [role=\"button\"], [role=\"link\"]'))\n              .filter((node) => {\n                const style = window.getComputedStyle(node);\n                return style.visibility !== 'hidden' && style.display !== 'none' && node.offsetParent !== null;\n              });\n            const el = candidates.find((node) => norm(node.innerText || node.textContent || '') === 'review');\n            if (!el) return { clicked: false };\n            el.click();\n            return { clicked: true, text: el.innerText || el.textContent || '' };\n        })()`);\n        if (!reviewClick || typeof reviewClick !== 'object' || typeof reviewClick.clicked !== 'boolean') {\n            throw new CommandExecutionError('Mercury returned malformed Review click result');\n        }\n        if (!reviewClick.clicked) {\n            throw new CommandExecutionError('Mercury Review button was not clicked; inspect the page for validation errors');\n        }\n        await page.wait({ time: 2 });\n        const review = await reviewSnapshot(page);\n        if (!review.hasReview || !review.hasSubmitExpenseButton) {\n            throw new CommandExecutionError('Mercury did not reach the Review step with the final Submit expense button visible');\n        }\n\n        if (input.closeAfterReview) {\n            await page.evaluate(`(() => {\n                const norm = (s) => String(s || '').replace(/\\\\s+/g, ' ').trim().toLowerCase();\n                const el = Array.from(document.querySelectorAll('button, a, [role=\"button\"], [role=\"link\"]'))\n                  .find((node) => norm(node.innerText || node.textContent || '') === 'close');\n                el?.click();\n                return { clicked: Boolean(el) };\n            })()`);\n            await page.wait({ time: 1 });\n        }\n","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/mercury/reimbursement-draft.js#L82-L118","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect the Mercury page for form validation errors and fix the underlying input (amount, date, receipt, merchant).","Re-run with the page fully loaded; a partially rendered SPA may not expose the Review button yet.","Check whether Mercury changed the button label/markup; update the text-match ('review') in reimbursement-draft.js if so.","Capture a screenshot or page snapshot at failure time to confirm what state the form is in."],"exampleFix":"// before\nthrow new CommandExecutionError('Mercury Review button was not clicked; inspect the page for validation errors');\n// after\nconst snapshot = await page.evaluate(`document.body.innerText.slice(0, 2000)`);\nthrow new CommandExecutionError(`Mercury Review button was not clicked; page state: ${snapshot}`);","handlingStrategy":"validation","validationCode":"// before invoking, confirm the form is fully rendered and no validation errors are visible\nconst ready = await page.evaluate(`(() => {\n    const norm = (s) => String(s || '').replace(/\\\\s+/g, ' ').trim().toLowerCase();\n    return Array.from(document.querySelectorAll('button, a, [role=button], [role=link]'))\n        .some((n) => norm(n.innerText || n.textContent || '') === 'review');\n})()`);\nif (!ready) throw new Error('Review button not present; fix form validation first');","typeGuard":"function canClickReview(snapshot) { return snapshot.ready === true && snapshot.validationErrors.length === 0; }","tryCatchPattern":"try {\n    await draftReimbursement(input);\n} catch (err) {\n    if (err.message.includes('Review button was not clicked')) {\n        const pageText = await page.evaluate('document.body.innerText');\n        throw new Error(`Form blocked Review: ${pageText.slice(0, 500)}`);\n    }\n    throw err;\n}","preventionTips":["Validate all form inputs (amount, date, receipt) before submitting upstream steps.","Wait for full render before attempting the Review click.","Snapshot the page on failure to capture validation banners.","Pin/update selectors when Mercury changes its UI."],"tags":["browser-automation","ui-selector","form-validation"],"backgroundTag":"ui-element-not-found","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}