jackwener/OpenCLI · error · CommandExecutionError

Unexpected Xiaohongshu search wait payload shape.

Error message

Unexpected Xiaohongshu search wait payload shape.

What it means

collectSearchHarvest expects the browser-side wait script to resolve to one of four known sentinels: 'login_wall', 'security_block', 'timeout', or 'content'. If the browser returns anything else — including null, undefined, or an object — the command throws this CommandExecutionError because it cannot classify the page state. This is a defensive contract check signaling the in-page instrumentation returned an unexpected shape.

Source

Thrown at clis/xiaohongshu/search.js:798

          },
        };
      })()
    `;
}

async function collectSearchHarvest(page, limit, requestedFilters) {
    const waitResult = unwrapEvaluateResult(await page.evaluate(WAIT_FOR_CONTENT_JS));
    if (waitResult === 'login_wall') {
        throw new AuthRequiredError('www.xiaohongshu.com', 'Xiaohongshu search results are blocked behind a login wall');
    }
    if (waitResult === 'security_block') {
        throw new CliError('SECURITY_BLOCK', 'Xiaohongshu search was blocked by request-frequency or security controls.', 'Wait before retrying or use a different logged-in browser session.');
    }
    if (waitResult === 'timeout') {
        throw new TimeoutError('xiaohongshu search content', CONTENT_WAIT_SECONDS);
    }
    if (waitResult !== 'content') {
        throw new CommandExecutionError('Unexpected Xiaohongshu search wait payload shape.');
    }
    requireFilterApplication(await page.evaluate(buildApplySearchFiltersJs(requestedFilters)));
    const harvestOptions = harvestOptionsForLimit(limit);
    const harvest = requireHarvestPayload(await page.evaluate(buildScrollHarvestJs('www.xiaohongshu.com', limit, harvestOptions)), 'www.xiaohongshu.com');
    if (harvest.diag.securityBlock) {
        throw new CliError('SECURITY_BLOCK', 'Xiaohongshu search was blocked by request-frequency or security controls.', 'Wait before retrying or use a different logged-in browser session.');
    }
    return harvest;
}

async function replaceCollapsedTab(page, url) {
    if (typeof page.getActivePage !== 'function' || typeof page.newTab !== 'function' ||
        typeof page.setActivePage !== 'function' || typeof page.selectTab !== 'function' ||
        typeof page.closeTab !== 'function') {
        throw new CommandExecutionError(
            'Xiaohongshu search rendered in a collapsed tab, but this browser session cannot replace the failed target.',
            'Retry the command in a Browser Bridge session that supports tab replacement.',
        );

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-run the command — a transient navigation failure can make evaluate resolve to undefined.
  2. Check whether the browser session/driver was modified or wrapped in a way that changes page.evaluate return values (e.g. result unwrapping).
  3. Inspect the actual waitResult: add temporary logging around page.evaluate(WAIT_FOR_CONTENT_JS) at clis/xiaohongshu/search.js:787.
  4. If you patched WAIT_FOR_CONTENT_JS, restore its documented return contract ('content' | 'login_wall' | 'security_block' | 'timeout').

Example fix

// before (modified wait script)
return { status: 'ok', state: 'content' };
// after (restore sentinel contract)
return 'content';
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

function isWaitPayloadShapeError(err) {
  return err?.name === 'CommandExecutionError' &&
    typeof err?.message === 'string' &&
    err.message.includes('Unexpected Xiaohongshu search wait payload shape');
}

Try / catch

try {
  rows = await cli('xiaohongshu search', query);
} catch (err) {
  if (isWaitPayloadShapeError(err)) {
    // internal contract break: retry once, then escalate/report rather than loop
    rows = await cli('xiaohongshu search', query);
  } else { throw err; }
}

Prevention

When it happens

Trigger: waitResult !== 'content' after the login_wall/security_block/timeout checks, i.e. page.evaluate(WAIT_FOR_CONTENT_JS) returned an unrecognized value — typically null/undefined from an evaluate serialization failure, or a modified WAIT_FOR_CONTENT_JS payload shape.

Common situations: Running a modified/monkey-patched WAIT_FOR_CONTENT_JS or an incompatible browser driver that fails evaluate silently; the page navigating away mid-wait so evaluate resolves to undefined; a locally edited checkout where the wait script's return contract was changed without updating this dispatcher.

Related errors


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