jackwener/OpenCLI · error · CommandExecutionError
Mercury returned malformed ${label}
Error message
Mercury returned malformed ${label} What it means
assertObject validates that Mercury (the browser automation backend) returned a non-null, non-array object under the given label. If the value is null/undefined, a primitive, or an array, it throws CommandExecutionError with 'Mercury returned malformed <label>'. This guards the boundary between the CLI and Mercury's JSON responses, which can degrade if the page/extension state is unexpected.
Source
Thrown at clis/mercury/utils.js:109
receipt: parseReceiptPath(kwargs),
amount: parseAmount(kwargs),
currency: parseCurrency(kwargs),
date: parseDate(kwargs),
merchant: requireString(kwargs, 'merchant'),
category: optionalString(kwargs, 'category', 'Marketing & Advertising'),
notes: requireString(kwargs, 'notes'),
ocrWaitSeconds: parseOcrWaitSeconds(kwargs),
closeAfterReview: optionalBoolean(kwargs, 'close-after-review', false),
};
}
export function receiptBasename(receipt) {
return path.basename(receipt);
}
export function assertObject(value, label) {
if (!value || typeof value !== 'object' || Array.isArray(value)) {
throw new CommandExecutionError(`Mercury returned malformed ${label}`);
}
return value;
}
export function assertMercuryState(value, label = 'page state') {
const state = assertObject(value, label);
if (typeof state.url !== 'string' || typeof state.title !== 'string') {
throw new CommandExecutionError(`Mercury returned malformed ${label}`);
}
return state;
}
function assertBooleanFields(state, label, fields) {
for (const field of fields) {
if (typeof state[field] !== 'boolean') {
throw new CommandExecutionError(`Mercury returned malformed ${label}: ${field} must be boolean`);
}
}View on GitHub (pinned to 49907e53dc)
Solutions
- Check that the Mercury extension/backend is running and the browser session is alive; restart the browser/Mercury if unsure.
- Log the raw value returned for the failing label to see what Mercury actually sent.
- Update Mercury/extension and CLI to matching versions so payload shapes align.
- Retry the command — transient page-state races often resolve on a fresh run.
Example fix
// before
const state = await mercury.getState(); // null when extension unloaded
// after
if (!state) throw new Error('Mercury extension not responding; reload extension and retry');
const checked = assertObject(state, 'page state'); Defensive patterns
Strategy: try-catch
Validate before calling
function looksLikeMercuryObject(v) {
return !!v && typeof v === 'object' && !Array.isArray(v);
} Type guard
function isMercuryObject(v) {
return typeof v === 'object' && v !== null && !Array.isArray(v);
} Try / catch
try {
const state = await inspectMercury(page);
} catch (e) {
if (e instanceof CommandExecutionError && e.message.includes('Mercury returned malformed')) {
console.error('Mercury payload unusable; reloading extension/session and retrying once...');
await restartMercury();
return inspectMercury(page);
}
throw e;
} Prevention
- Health-check the Mercury extension before running batches
- Keep Mercury extension and CLI versions in sync
- Retry once on transient malformed payloads
- Log raw payloads on failure for diagnosis
When it happens
Trigger: Mercury returns null/undefined where a state object was expected; returns an array instead of an object; a code path returns a string/number (e.g. an error message string) that is fed to assertObject/state.
Common situations: Mercury extension not loaded or crashed so the bridge returns null; page navigated away so the snapshot is empty; version mismatch where Mercury returns a differently-shaped payload; network/timeout yielding an error string instead of JSON.
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
- Mercury returned malformed ${label}: ${field} must be boolea
- Bilibili creator comparison returned malformed stat data for
- Bilibili creator comparison returned malformed metric ${defi
- Bilibili creator comparison returned non-integer metric ${de
- Bilibili view API returned a malformed payload during paid-c
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/c81e7d26b943088b.
Report an issue: GitHub.