{"record":{"id":"af884ed88cab7c92","repo":"jackwener/OpenCLI","slug":"xiaohongshu-follow-malformed-context-payload","errorCode":null,"errorMessage":"xiaohongshu/follow: malformed ${context} payload","messagePattern":"xiaohongshu/follow: malformed (.+?) payload","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/xiaohongshu/follow.js","lineNumber":35,"sourceCode":" */\nimport { cli, Strategy } from '@jackwener/opencli/registry';\nimport { ArgumentError, AuthRequiredError, CliError, CommandExecutionError } from '@jackwener/opencli/errors';\nimport { normalizeXhsUserId } from './user-helpers.js';\nimport { unwrapEvaluateResult } from './shared.js';\n\nconst PROFILE_SETTLE_MS = 2500;\nconst STATE_FLIP_TIMEOUT_MS = 5000;\nconst USER_ID_RE = /^[a-zA-Z0-9]{8,32}$/;\n\nfunction isXiaohongshuHost(hostname) {\n    const host = String(hostname || '').toLowerCase();\n    return host === 'xiaohongshu.com' || host.endsWith('.xiaohongshu.com');\n}\n\nfunction requireActionResult(payload, context) {\n    const inner = unwrapEvaluateResult(payload);\n    if (!inner || typeof inner !== 'object' || Array.isArray(inner) || typeof inner.ok !== 'boolean') {\n        throw new CommandExecutionError(`xiaohongshu/follow: malformed ${context} payload`);\n    }\n    return inner;\n}\n\nfunction assertUserId(raw) {\n    const input = String(raw ?? '').trim();\n    if (/^https?:\\/\\//i.test(input)) {\n        let parsed;\n        try {\n            parsed = new URL(input);\n        } catch {\n            throw new ArgumentError('xiaohongshu/follow: invalid profile URL');\n        }\n        if (parsed.protocol !== 'https:' || !isXiaohongshuHost(parsed.hostname)) {\n            throw new ArgumentError('xiaohongshu/follow: profile URL must be an exact https://*.xiaohongshu.com URL');\n        }\n        const match = parsed.pathname.match(/^\\/user\\/profile\\/([a-zA-Z0-9]{8,32})\\/?$/);\n        if (!match) {","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xiaohongshu/follow.js#L17-L53","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before\nconst inner = unwrapEvaluateResult(payload);\nif (!inner || typeof inner.ok !== 'boolean') throw new CommandExecutionError(`...malformed ${context} payload`);\n// after\nconst inner = unwrapEvaluateResult(payload);\nif (!inner || typeof inner !== 'object' || typeof inner.ok !== 'boolean') {\n  console.error('raw payload:', payload); // debug the actual shape\n  throw new CommandExecutionError(`...malformed ${context} payload`);\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"function isActionResult(p) {\n  return !!p && typeof p === 'object' && !Array.isArray(p) && typeof p.ok === 'boolean';\n}","tryCatchPattern":"try {\n  await follow(page, userId);\n} catch (err) {\n  if (err.code === 'COMMAND_EXEC' && err.message.includes('malformed')) {\n    // retry once; then verify bridge/extension health\n  }\n  throw err;\n}","preventionTips":["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"],"tags":["payload-validation","browser-automation","page-evaluate","xiaohongshu"],"backgroundTag":"unexpected-payload-shape","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}