{"record":{"id":"fc8ad2b383066fdc","repo":"jackwener/OpenCLI","slug":"xiaohongshu-unfollow-malformed-current-url-payloa","errorCode":null,"errorMessage":"xiaohongshu/unfollow: malformed current-url payload","messagePattern":"xiaohongshu/unfollow: malformed current-url payload","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/xiaohongshu/unfollow.js","lineNumber":211,"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 unfollow');\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/unfollow: 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/unfollow: 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/unfollow: expected profile ${userId}, got ${parsedHref.pathname}`,\n                );\n            }\n\n            // Step 1: click 已关注 (idempotent — bails out if 关注 is visible)","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xiaohongshu/unfollow.js#L193-L229","documentation":"After navigating to the profile URL and settling, the command reads location.href via page.evaluate and unwraps it with unwrapEvaluateResult. If the unwrapped value is not a string, the browser bridge returned something unexpected, so this CommandExecutionError is thrown to fail fast rather than call new URL() on garbage.","triggerScenarios":"page.evaluate returning a non-string payload — e.g. the wrapper returned {value: ...}, an array, undefined, or a serialized error object instead of a raw string; a custom/driver-specific evaluate that wraps results; a proxy or patched evaluate injecting metadata; navigation failing so the evaluate result is an error object.","commonSituations":"Using a different driver/automation layer whose evaluate result shape differs from what the CLI expects; library version mismatch where unwrapEvaluateResult conventions changed; page crashed or was closed mid-evaluate so the promise resolves with a non-string sentinel.","solutions":["Update the CLI/driver packages so page.evaluate and unwrapEvaluateResult use the same result-wrapping convention","Confirm you are using the library's own page object/driver, not a custom evaluate wrapper that changes return shapes","Re-run the command — a transient page crash or navigation race can produce a non-string result; also increase settle time if the page was still loading","Inspect what page.evaluate('() => location.href') actually returns in your environment and adapt (it must be a plain string)"],"exampleFix":"// before\nconst href = await myWrapper.evaluate(page, '() => location.href'); // returns { value: '...' }\n// after\nconst href = unwrapEvaluateResult(await page.evaluate('() => location.href')); // string","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isString(v) { return typeof v === 'string'; }\n// usage: const href = unwrapEvaluateResult(raw); if (!isString(href)) fallBackOrRetry();","tryCatchPattern":"try { await cli.unfollow({ 'user-id': id }); } catch (e) { if (String(e.message).includes('malformed current-url payload')) { /* retry once with the library's own driver, or upgrade library versions */ } else throw e; }","preventionTips":["Use the library's own page/driver so evaluate result shapes match","Keep the CLI and driver packages on compatible versions","Retry transient navigation failures instead of treating them as fatal","Log the raw evaluate result when debugging wrapper integrations"],"tags":["browser","payload-shape","automation"],"backgroundTag":"unexpected-evaluate-payload","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}