{"record":{"id":"cfb3f5b7f3850091","repo":"jackwener/OpenCLI","slug":"xiaohongshu-follow-failed-result-reason-unk","errorCode":null,"errorMessage":"xiaohongshu/follow failed: ${result.reason ?? 'unknown reason'}","messagePattern":"xiaohongshu/follow failed: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/xiaohongshu/follow.js","lineNumber":203,"sourceCode":"                    `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(\n                await page.evaluate(buildFollowScript()),\n                'follow-action',\n            );\n            if (!result.ok) {\n                throw new CommandExecutionError(\n                    `xiaohongshu/follow failed: ${result.reason ?? 'unknown reason'}`,\n                );\n            }\n            return [{ status: result.state, user_id: userId, url }];\n        } catch (err) {\n            if (err instanceof CliError) throw err;\n            throw new CommandExecutionError(\n                `xiaohongshu/follow failed: ${err?.message ?? String(err)}`,\n            );\n        }\n    },\n});\n\nexport const __test__ = {\n    assertUserId,\n    buildFollowScript,\n};\n","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xiaohongshu/follow.js#L185-L221","documentation":"Thrown when the in-page follow script runs but reports failure via result.ok === false. requireActionResult guarantees the payload shape, so reaching this throw means the DOM automation itself failed (button not found, click did not flip state, etc.) and the script returned a reason. The command surfaces result.reason, or 'unknown reason' when absent.","triggerScenarios":"page.evaluate(buildFollowScript()) returns { ok: false, reason } — the follow button was not located in the profile header, the button text never flipped to 已关注 within the 5s STATE_FLIP_TIMEOUT_MS, or the click was intercepted.","commonSituations":"User already blocked/restricted interactions; XHS DOM changed so selectors no longer match; page not fully settled when the script ran; network slowness exceeding the 5s poll window.","solutions":["Read result.reason in the message and address the specific failure (e.g. button-not-found vs timeout).","Retry — transient rendering delays commonly cause the state-flip timeout.","Manually confirm the follow action works in the logged-in browser; re-login if the session is degraded.","Update the CLI if XHS changed its profile-header DOM."],"exampleFix":"// before\nawait cli.run(['xiaohongshu', 'follow', userId]); // flaky first attempt\n// after\ntry {\n  await cli.run(['xiaohongshu', 'follow', userId]);\n} catch (e) {\n  if (/timeout|button/i.test(e.message)) await cli.run(['xiaohongshu', 'follow', userId]); // one retry\n  else throw e;\n}","handlingStrategy":"retry","validationCode":"// Confirm session is live before automating\nconst probe = await page.evaluate(() => !!document.querySelector('[role=button], button'));\nif (!probe) throw new Error('page not ready for follow action');","typeGuard":"function isActionResult(v) {\n  return !!v && typeof v === 'object' && !Array.isArray(v) && typeof v.ok === 'boolean';\n}","tryCatchPattern":"try {\n  await follow(userId);\n} catch (err) {\n  if (/follow failed/.test(err.message)) {\n    await sleep(2000);\n    await follow(userId); // single retry for transient DOM/timing issues\n  } else throw err;\n}","preventionTips":["Allow the profile page to fully settle before automation runs.","Retry once on failure — state-flip timeouts are often transient.","Keep the CLI updated for XHS DOM changes.","Verify the account isn't action-limited by following manually first."],"tags":["xiaohongshu","dom-automation","follow-action"],"backgroundTag":"page-action-script-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}