jackwener/OpenCLI · error · CommandExecutionError
Mercury returned malformed Review click result
Error message
Mercury returned malformed Review click result
What it means
This CLI drives the Mercury web UI via browser automation. After executing an in-page script that finds and clicks the 'Review' button, it validates the returned result object before proceeding. If the result is not an object with a boolean `clicked` field (e.g. the evaluate returned null/undefined because the script threw or the page context changed), this error is thrown because the automation cannot tell whether the click happened.
Source
Thrown at clis/mercury/reimbursement-draft.js:97
const missing = expectedFields.filter((key) => !fields.touched[key]);
if (missing.length > 0) {
throw new CommandExecutionError(`Mercury reimbursement form fields were not all filled: ${missing.join(', ')}`);
}
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) };
})()`);View on GitHub (pinned to 49907e53dc)
Solutions
- Re-run the command; transient page-load races often resolve on a retry with the page fully loaded.
- Increase the wait before the click step so the Mercury SPA is fully rendered before evaluating the script.
- Verify the browser/driver session is healthy and the page has not navigated away from the expense form.
- If persistent, inspect whether Mercury's DOM changed such that the in-page script throws (check the browser console); update the selector/script in reimbursement-draft.js.
Example fix
// before
const reviewClick = await page.evaluate(`...`);
if (!reviewClick || typeof reviewClick !== 'object' || typeof reviewClick.clicked !== 'boolean') {
throw new CommandExecutionError('Mercury returned malformed Review click result');
}
// after
await page.wait({ time: 2 }); // ensure SPA is settled before clicking
const reviewClick = await page.evaluate(`...`);
if (!reviewClick || typeof reviewClick !== 'object' || typeof reviewClick.clicked !== 'boolean') {
throw new CommandExecutionError('Mercury returned malformed Review click result');
} Defensive patterns
Strategy: type-guard
Validate before calling
const r = await page.evaluate(`...`); const isClickResult = (v) => v !== null && typeof v === 'object' && typeof v.clicked === 'boolean';
Type guard
function isClickResult(v) { return v !== null && typeof v === 'object' && typeof v.clicked === 'boolean'; } Try / catch
try {
const reviewClick = await page.evaluate(`...`);
if (!isClickResult(reviewClick)) throw new CommandExecutionError('Mercury returned malformed Review click result');
} catch (err) {
if (err instanceof CommandExecutionError) throw err;
await page.wait({ time: 2 }); // retry once after settle, then rethrow
throw err;
} Prevention
- Wait for the SPA to settle before running in-page click scripts.
- Retry evaluate-based steps once on transient failures.
- Assert the page URL/state before executing the click script.
- Keep the in-page script defensive so it always returns an object, even on DOM changes.
When it happens
Trigger: The page.evaluate snippet returning the click result yields null, undefined, a non-object, or an object without a boolean `clicked` property — e.g. the script was interrupted by a navigation, the page context was destroyed, or the browser driver returned an unexpected serialization of the result.
Common situations: Slow Mercury SPA mid-render when the evaluate runs, page navigation triggered right as the script executes, browser session/driver issues returning undefined from evaluate, or a Mercury DOM change breaking the script so it never returns a value.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- targetCount must be an integer between 1 and 100, got ${JSON
- maxScrolls must be an integer between 1 and 30, got ${JSON.s
- Gemini image export returned a malformed result
- Unexpected 12306 probe: ${JSON.stringify(probe)}
- Waiting for 12306 tk auth cookie
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/10abf21731f180f2.
Report an issue: GitHub.