{"record":{"id":"0006d0792894f92b","repo":"jackwener/OpenCLI","slug":"xiaohongshu-follow-malformed-current-url-payload","errorCode":null,"errorMessage":"xiaohongshu/follow: malformed current-url payload","messagePattern":"xiaohongshu/follow: malformed current-url payload","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/xiaohongshu/follow.js","lineNumber":180,"sourceCode":"            required: true,\n            positional: true,\n            help: 'User ID (e.g. 5d8f88dc0000000001005d3a) or profile URL',\n        },\n    ],\n    columns: ['status', 'user_id', 'url'],\n    func: async (page, kwargs) => {\n        if (!page) {\n            throw new CommandExecutionError('Browser session required for xiaohongshu follow');\n        }\n        try {\n            const userId = assertUserId(kwargs['user-id']);\n            const url = `https://www.xiaohongshu.com/user/profile/${userId}`;\n            await page.goto(url);\n            await page.wait({ time: PROFILE_SETTLE_MS / 1000 });\n\n            const hrefRaw = unwrapEvaluateResult(await page.evaluate('() => location.href'));\n            if (typeof hrefRaw !== 'string') {\n                throw new CommandExecutionError('xiaohongshu/follow: malformed current-url payload');\n            }\n            const parsedHref = new URL(hrefRaw);\n            if (parsedHref.protocol !== 'https:' || !isXiaohongshuHost(parsedHref.hostname)) {\n                throw new CommandExecutionError(\n                    `xiaohongshu/follow: expected Xiaohongshu profile host, got ${parsedHref.hostname}`,\n                );\n            }\n            if (/\\/login(?:[/?#]|$)/i.test(parsedHref.pathname)) {\n                throw new AuthRequiredError('www.xiaohongshu.com');\n            }\n            const currentProfile = parsedHref.pathname.match(/^\\/user\\/profile\\/([a-zA-Z0-9]{8,32})\\/?$/);\n            if (currentProfile?.[1] !== userId) {\n                throw new CommandExecutionError(\n                    `xiaohongshu/follow: expected profile ${userId}, got ${parsedHref.pathname}`,\n                );\n            }\n\n            const result = requireActionResult(","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xiaohongshu/follow.js#L162-L198","documentation":"After navigating to the profile and settling, the command reads location.href via page.evaluate and requires it to be a plain string after unwrapEvaluateResult. A non-string result means the in-page evaluation did not return the expected value, so the command aborts with CommandExecutionError rather than acting on bad data.","triggerScenarios":"The evaluate returned null/undefined (page navigated or context destroyed mid-run), an Error object from the page, or an object wrapper from the extension bridge that unwrapEvaluateResult couldn't flatten.","commonSituations":"The site redirected (login wall, captcha) while waiting PROFILE_SETTLE_MS, destroying the eval context; a JS dialog blocking evaluation; stale extension bridge after reconnect; site CSP changes breaking the injected script.","solutions":["Re-run the command; transient context destruction usually resolves on retry.","Log in to www.xiaohongshu.com in the connected browser so no redirect happens during settle.","Increase the settle wait or close interfering dialogs/tabs on the profile page.","Check the extension/daemon version and unwrapEvaluateResult handling if payloads are consistently non-strings."],"exampleFix":"// before\nconst hrefRaw = unwrapEvaluateResult(await page.evaluate('() => location.href'));\nif (typeof hrefRaw !== 'string') throw new CommandExecutionError('...malformed current-url payload');\n// after\nconst hrefRaw = unwrapEvaluateResult(await page.evaluate('() => location.href'));\nif (typeof hrefRaw !== 'string') {\n  console.error('location.href evaluate returned:', hrefRaw); // inspect and handle wrapper\n  throw new CommandExecutionError('...malformed current-url payload');\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":"function isString(x) { return typeof x === 'string'; }","tryCatchPattern":"try {\n  await follow(page, userId);\n} catch (err) {\n  if (err.code === 'COMMAND_EXEC' && err.message.includes('malformed current-url')) {\n    await sleep(1000);\n    return follow(page, userId); // retry once after settle\n  }\n  throw err;\n}","preventionTips":["Don't interact with the tab while the command runs","Dismiss dialogs/captcha before invoking follow","Keep the extension bridge healthy (restart browser on repeated failures)","Log in beforehand so no mid-run redirect destroys the eval context"],"tags":["page-evaluate","payload-validation","browser-automation","xiaohongshu"],"backgroundTag":"unexpected-payload-shape","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}