jackwener/OpenCLI · error · CommandExecutionError

xiaohongshu ask returned a malformed page payload: missing a

Error message

xiaohongshu ask returned a malformed page payload: missing answer

What it means

requireAskPayload throws this when the returned object exists but has no usable answer text: cleanText(raw.answer || raw.base_info?.text) is empty. The page responded but 点点 did not produce (or the script did not extract) an answer body, so the library refuses to return a hollow result.

Source

Thrown at clis/xiaohongshu/ask.js:383

    if (error === 'answer_timeout') {
        throw new TimeoutError('xiaohongshu ask', timeoutSeconds, '点点没有在超时时间内返回答案;可以重试或提高 --timeout。');
    }
    if (error === 'send_message_failed') {
        throw new AuthRequiredError(XHS_WEB_HOST, 'Xiaohongshu 点点 did not accept the query. Check login status for www.xiaohongshu.com.');
    }
    throw new CommandExecutionError(
        `xiaohongshu ask failed: ${error || 'unknown error'}`,
        raw?.page_url ? `Page URL: ${raw.page_url}` : undefined,
    );
}

function requireAskPayload(raw) {
    if (!raw || typeof raw !== 'object') {
        throw new CommandExecutionError('xiaohongshu ask returned a malformed page payload');
    }
    const answer = cleanText(raw.answer || raw.base_info?.text || '');
    if (!answer) {
        throw new CommandExecutionError('xiaohongshu ask returned a malformed page payload: missing answer');
    }
    if (!compactSingleLine(raw.message_id) || !compactSingleLine(raw.conversation_id)) {
        throw new CommandExecutionError('xiaohongshu ask returned a malformed page payload: missing message identity');
    }
}

export const command = cli({
    site: 'xiaohongshu',
    name: 'ask',
    access: 'write',
    description: 'Ask 小红书点点 and return the answer with citation sources.',
    domain: XHS_WEB_HOST,
    strategy: Strategy.COOKIE,
    browser: true,
    navigateBefore: false,
    args: [
        { name: 'query', positional: true, required: true, help: 'Question for 点点' },
        { name: 'timeout', type: 'int', default: 90, help: 'Seconds to wait for the 点点 answer' },

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Increase --timeout so the script polls longer for 点点's reply.
  2. Retry the command; the first attempt may have raced the reply rendering.
  3. Re-login to rule out restricted-account behavior.
  4. Update the library if the XHS answer DOM changed.
  5. Test with a different/simpler query to see whether replies render at all.

Example fix

// before
await cli.run(['xiaohongshu','ask','--query','...','--timeout','15']);
// after
await cli.run(['xiaohongshu','ask','--query','...','--timeout','60']);
Defensive patterns

Strategy: retry

Try / catch

try {
  return await xiaohongshuAsk({ query, timeout: 60 });
} catch (e) {
  if (/missing answer/.test(e.message)) {
    await sleep(3000);
    return xiaohongshuAsk({ query, timeout: 60 }); // reply may render late
  }
  throw e;
}

Prevention

When it happens

Trigger: raw is an object whose answer and base_info.text are both missing/empty/whitespace after cleanText — e.g. the answer was still streaming, or XHS rendered the reply in a DOM node the selector no longer matches.

Common situations: Query sent but 点点 hasn't replied within the polling window (answer still empty); XHS redesigned the answer DOM so extraction finds nothing; the reply was removed/filtered; account restrictions suppress AI replies.

Understand the failure class

Related errors


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