jackwener/OpenCLI · error · CommandExecutionError

Xianyu ${label} returned malformed browser payload

Error message

Xianyu ${label} returned malformed browser payload

What it means

This error is thrown by requireEvaluateObject when the result of a page.evaluate() browser-script call is not a non-null, non-array plain object. The library expects every injected extraction/click script to return a structured object payload; anything else (null, undefined, an array, a primitive) means the browser script failed to execute properly or the page context is broken. It is thrown as a CommandExecutionError because the browser-side command did not produce usable output.

Source

Thrown at clis/xianyu/im.js:44

    }
    const n = Number(raw);
    if (!Number.isSafeInteger(n) || n < 1) {
        throw new ArgumentError('xianyu rank must be a positive integer from xianyu inbox');
    }
    return n;
}

export function requireText(value, label) {
    const text = String(value ?? '').replace(/\s+/g, ' ').trim();
    if (!text) {
        throw new ArgumentError(`${label} cannot be empty`);
    }
    return text;
}

export function requireEvaluateObject(payload, label) {
    if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
        throw new CommandExecutionError(`Xianyu ${label} returned malformed browser payload`);
    }
    return payload;
}

export function requireClickResult(payload, label) {
    const result = requireEvaluateObject(payload, label);
    if (result.ok !== true) {
        throw new CommandExecutionError(`Xianyu ${label} failed: ${result.reason || 'unknown-reason'}`);
    }
    return result;
}

export function buildChatUrl(itemId, peerUserId) {
    return `https://www.goofish.com/im?itemId=${encodeURIComponent(itemId)}&peerUserId=${encodeURIComponent(peerUserId)}`;
}

export function buildInboxUrl() {
    return 'https://www.goofish.com/im';

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-login / restart the browser session so page.evaluate runs against a live document
  2. Retry the command; transient SPA navigation can make evaluate return undefined once
  3. Run without --resolve-ids to isolate whether the click-navigation path is the failing evaluate
  4. Update the browser driver/automation runtime so evaluate results are serialized as JSON objects
  5. Catch the error and inspect page.getCurrentUrl() to confirm the session is still on www.goofish.com/im

Example fix

// before
const payload = requireEvaluateObject(await page.evaluate(buildExtractInboxEvaluate(limit)), 'inbox');
// after
let raw;
try {
  raw = await page.evaluate(buildExtractInboxEvaluate(limit));
} catch (e) {
  await page.goto(buildInboxUrl());
  await page.wait(4);
  raw = await page.evaluate(buildExtractInboxEvaluate(limit));
}
const payload = requireEvaluateObject(raw, 'inbox');
Defensive patterns

Strategy: validation

Validate before calling

function isValidEvaluatePayload(v) {
  return v !== null && typeof v === 'object' && !Array.isArray(v);
}
// check before using: if (!isValidEvaluatePayload(raw)) re-navigate and retry;

Type guard

function isEvaluateObject(v) {
  return v !== null && typeof v === 'object' && !Array.isArray(v);
}
if (isEvaluateObject(raw)) { const payload = raw; /* payload is a plain object */ }

Try / catch

try {
  const payload = requireEvaluateObject(await page.evaluate(script), 'inbox');
} catch (e) {
  if (String(e).includes('malformed browser payload')) {
    await page.goto('https://www.goofish.com/im');
    await page.wait(4);
    // retry once, else surface the error
  } else throw e;
}

Prevention

When it happens

Trigger: Calling any command that uses requireEvaluateObject (inbox, chat read, send-message, resolve-ids click, current-url read) when page.evaluate returns null/undefined, an array, or a primitive — e.g. the evaluate script threw inside the browser and the driver swallowed it into undefined, the page navigated/closed mid-evaluate, or the browser session is stale so evaluate returns nothing.

Common situations: Expired or crashed browser session where the page handle is dead; the goofish.com SPA navigated between goto and evaluate; a driver version change that serializes evaluate results differently (returning undefined instead of an object); calling with --resolve-ids when the conversation row click triggers a full navigation so the follow-up evaluate returns undefined.

Understand the failure class

Related errors


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