jackwener/OpenCLI · error · CommandExecutionError
xiaohongshu/follow: malformed ${context} payload
Error message
xiaohongshu/follow: malformed ${context} payload What it means
requireActionResult validates that the payload returned from page.evaluate() unwraps to an object with a boolean ok field; anything else is a CommandExecutionError. It guards the bridge between the CLI and in-page script results. A malformed payload means the injected script did not return the expected { ok: boolean, ... } shape.
Source
Thrown at clis/xiaohongshu/follow.js:35
*/
import { cli, Strategy } from '@jackwener/opencli/registry';
import { ArgumentError, AuthRequiredError, CliError, CommandExecutionError } from '@jackwener/opencli/errors';
import { normalizeXhsUserId } from './user-helpers.js';
import { unwrapEvaluateResult } from './shared.js';
const PROFILE_SETTLE_MS = 2500;
const STATE_FLIP_TIMEOUT_MS = 5000;
const USER_ID_RE = /^[a-zA-Z0-9]{8,32}$/;
function isXiaohongshuHost(hostname) {
const host = String(hostname || '').toLowerCase();
return host === 'xiaohongshu.com' || host.endsWith('.xiaohongshu.com');
}
function requireActionResult(payload, context) {
const inner = unwrapEvaluateResult(payload);
if (!inner || typeof inner !== 'object' || Array.isArray(inner) || typeof inner.ok !== 'boolean') {
throw new CommandExecutionError(`xiaohongshu/follow: malformed ${context} payload`);
}
return inner;
}
function assertUserId(raw) {
const input = String(raw ?? '').trim();
if (/^https?:\/\//i.test(input)) {
let parsed;
try {
parsed = new URL(input);
} catch {
throw new ArgumentError('xiaohongshu/follow: invalid profile URL');
}
if (parsed.protocol !== 'https:' || !isXiaohongshuHost(parsed.hostname)) {
throw new ArgumentError('xiaohongshu/follow: profile URL must be an exact https://*.xiaohongshu.com URL');
}
const match = parsed.pathname.match(/^\/user\/profile\/([a-zA-Z0-9]{8,32})\/?$/);
if (!match) {View on GitHub (pinned to 49907e53dc)
Solutions
- Re-run the command — transient navigation/bridge failures often resolve on a second attempt.
- Verify the connected browser extension/daemon is current (restart the browser and opencli connection).
- Inspect what page.evaluate returns for location/profile actions and confirm it is { ok: boolean, ... }; update unwrapEvaluateResult or the injected script if the shape changed.
- Check for page navigation or dialog interrupting the evaluate (add waits before evaluating).
Example fix
// before
const inner = unwrapEvaluateResult(payload);
if (!inner || typeof inner.ok !== 'boolean') throw new CommandExecutionError(`...malformed ${context} payload`);
// after
const inner = unwrapEvaluateResult(payload);
if (!inner || typeof inner !== 'object' || typeof inner.ok !== 'boolean') {
console.error('raw payload:', payload); // debug the actual shape
throw new CommandExecutionError(`...malformed ${context} payload`);
} Defensive patterns
Strategy: type-guard
Type guard
function isActionResult(p) {
return !!p && typeof p === 'object' && !Array.isArray(p) && typeof p.ok === 'boolean';
} Try / catch
try {
await follow(page, userId);
} catch (err) {
if (err.code === 'COMMAND_EXEC' && err.message.includes('malformed')) {
// retry once; then verify bridge/extension health
}
throw err;
} Prevention
- Keep the browser extension/daemon up to date
- Avoid navigating or opening dialogs on the tab while the command runs
- Retry once on malformed-payload errors before failing hard
- Log raw evaluate payloads when debugging
When it happens
Trigger: The evaluate() call inside the follow command returned null, undefined, an array, a non-object, or an object without ok === true|false — e.g. the page script threw and returned undefined, the extension bridge wrapped/failed the result, or the script was updated to a different shape.
Common situations: Page navigated away mid-evaluate so the script never ran; browser extension returned an { value: ... } wrapper not handled by unwrapEvaluateResult; a site update replaced the global the script relies on; stale browser bridge after the extension reconnected.
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
- xiaohongshu/follow: malformed current-url payload
- ${label}: ${String(payload.error)}
- ${label} returned malformed extraction payload
- Codex extract-diff returned an invalid payload.
- coupang add-to-cart evaluation failed: ${error?.message || e
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/af884ed88cab7c92.
Report an issue: GitHub.