jackwener/OpenCLI · error · CommandExecutionError
Could not find the Mercury Submit expense or New expense but
Error message
Could not find the Mercury Submit expense or New expense button
What it means
After opening the create-expense surface, the flow calls clickCreateExpenseButton; if no button matching 'Submit expense' or 'New expense' is found/clickable, it throws CommandExecutionError. This means Mercury's UI did not present the expected create-expense entry point, so the automation cannot proceed safely.
Source
Thrown at clis/mercury/reimbursement-draft.js:54
{ name: 'ocr-wait-seconds', default: '8', help: 'Seconds to wait after receipt upload before correcting OCR-overwritten fields' },
{ name: 'close-after-review', type: 'boolean', default: false, help: 'Close the Review dialog after verification; final Submit is still never clicked' },
],
columns: ['status', 'url', 'receipt', 'uploaded', 'fieldsTouched', 'reviewReady', 'submitBlocked', 'warnings'],
func: async (page, kwargs) => {
const input = normalizeReimbursementInput(kwargs);
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');
}View on GitHub (pinned to 49907e53dc)
Solutions
- Log in manually and confirm the 'Submit expense'/'New expense' button exists on the expenses page; complete any interstitials (onboarding, verification) first.
- Refresh the page or restart the browser session and retry once the page fully loads.
- Verify your Mercury user has permission to create/submit expenses in the workspace.
- If the button exists but the automation still fails, the selectors in clis/mercury/reimbursement-draft.js (assertCreateExpenseSurface/clickCreateExpenseButton) are likely stale — update them or report the Mercury UI change upstream.
Example fix
// before (partial load)
await page.goto(MERCURY_EXPENSES_URL, { waitUntil: 'load' });
const opened = await clickCreateExpenseButton(page);
// after (ensure surface settled before clicking)
await page.goto(MERCURY_EXPENSES_URL, { waitUntil: 'load', settleMs: 3000 });
await page.wait({ selector: 'button', timeout: 10 });
const opened = await clickCreateExpenseButton(page); Defensive patterns
Strategy: try-catch
Validate before calling
// preflight: confirm the create-expense button is present before invoking
const ok = await page.evaluate(`!![...document.querySelectorAll('button')]
.find(b => /(submit expense|new expense)/i.test(b.textContent || ''))`);
if (!ok) throw new Error('Create-expense button not on page; load fully or check permissions'); Try / catch
try {
await draftReimbursement(page, data);
} catch (e) {
if (/Could not find the Mercury Submit expense/.test(e.message)) {
console.error('Reload the expenses page, clear interstitials, verify permissions, or update stale selectors');
} else throw e;
} Prevention
- Wait for full page load/settling before clicking; add selector waits.
- Complete any onboarding/2FA interstitials manually before automating.
- Confirm the Mercury role has expense-creation permissions.
- After Mercury UI releases, re-verify selectors in clis/mercury/reimbursement-draft.js and update them promptly.
When it happens
Trigger: Running reimbursement-draft when Mercury's UI changed (selectors/markup updated), the user lacks permission to create expenses, the account/workspace shows a different expenses layout, the page loaded partially (network slowness), or an unexpected interstitial (2FA, onboarding, error banner) replaced the normal view.
Common situations: Mercury product UI updates breaking selectors; new workspaces with restricted roles; A/B-tested layouts; slow loads where the button hasn't rendered before the click attempt; sessions landing on a different locale's labels.
Related errors
- Mercury appears to have an existing expense review open; ref
- ${label} click failed
- 当前浏览器适配器不支持文件注入
- Mercury reimbursement-draft requires Browser Bridge uploadFi
- Mercury receipt upload did not confirm exactly one uploaded
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/f6b569a9b53e047d.
Report an issue: GitHub.