jackwener/OpenCLI · error · CommandExecutionError

xiaohongshu/unfollow: ${verifyRaw?.reason ?? 'state verifica

Error message

xiaohongshu/unfollow: ${verifyRaw?.reason ?? 'state verification failed'}

What it means

After unfollowing, step 3 re-evaluates the profile page (buildVerifyFollowFlippedScript) to confirm the follow button text flipped back to 关注. The script returned an object without ok===true and reported its own reason (or none), so the command throws CommandExecutionError. This is a post-action state verification: the click succeeded but the page state did not reflect the unfollow.

Source

Thrown at clis/xiaohongshu/unfollow.js:260

            // Step 2: confirm the unfollow modal. Wait for the modal to mount
            // first — xhs uses a CSS transition before the footer becomes
            // interactive.
            await page.wait({ time: MODAL_SETTLE_MS / 1000 });
            const confirmResult = requireActionResult(
                await page.evaluate(buildConfirmModalScript()),
                'confirm-modal',
            );
            if (!confirmResult.ok) {
                throw new CommandExecutionError(
                    `xiaohongshu/unfollow: confirmation modal step failed (${confirmResult.kind ?? 'no kind reported'})`,
                );
            }

            // Step 3: verify the profile button text flipped back to 关注.
            const verifyRaw = unwrapEvaluateResult(await page.evaluate(buildVerifyFollowFlippedScript()));
            if (!verifyRaw || typeof verifyRaw !== 'object' || verifyRaw.ok !== true) {
                throw new CommandExecutionError(
                    `xiaohongshu/unfollow: ${verifyRaw?.reason ?? 'state verification failed'}`,
                );
            }
            return [{ status: 'unfollowed', user_id: userId, url }];
        } catch (err) {
            if (err instanceof CliError) throw err;
            throw new CommandExecutionError(
                `xiaohongshu/unfollow failed: ${err?.message ?? String(err)}`,
            );
        }
    },
});

export const __test__ = {
    assertUserId,
    buildClickUnfollowScript,
    buildConfirmModalScript,
    buildVerifyFollowFlippedScript,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-run the command — check if the unfollow actually persisted on the site (the click may have worked despite verification failing)
  2. Add a small wait/retry between the confirm click and the verify evaluate to allow the UI to re-render
  3. Update buildVerifyFollowFlippedScript's button-text/selector expectations after any xiaohongshu.com frontend change
  4. Verify the account session is healthy (rate-limited or expired sessions can silently no-op the unfollow)

Example fix

// before
const verifyRaw = unwrapEvaluateResult(await page.evaluate(buildVerifyFollowFlippedScript()));
if (!verifyRaw || typeof verifyRaw !== 'object' || verifyRaw.ok !== true) {
// after
let verifyRaw;
for (let attempt = 0; attempt < 3; attempt++) {
    verifyRaw = unwrapEvaluateResult(await page.evaluate(buildVerifyFollowFlippedScript()));
    if (verifyRaw?.ok === true) break;
    await page.wait({ time: 1 });
}
if (!verifyRaw || typeof verifyRaw !== 'object' || verifyRaw.ok !== true) {
Defensive patterns

Strategy: retry

Validate before calling

const btn = await page.evaluate(() => document.body.innerText.includes('已关注'));
if (!btn) throw new Error('target does not appear followed; unfollow unnecessary');

Type guard

function isVerifiedFlip(v) { return v && typeof v === 'object' && v.ok === true; }

Try / catch

try {
  await unfollow(userId);
} catch (err) {
  if (/state verification failed|unfollow: /.test(err.message)) {
    await wait(2000); // allow UI re-render, then verify manually or retry
  } else throw err;
}

Prevention

When it happens

Trigger: The verify script found the button still showing 已关注 (unfollow did not actually take effect), the button markup changed so the text check failed, or the page had not re-rendered yet when the script ran.

Common situations: Site redesign changes button label/structure; server accepted the unfollow but UI lags; rate limiting silently rejects the unfollow API call; stale cached page after evaluate.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/d873c5b7463b7cf5. Report an issue: GitHub.