jackwener/OpenCLI · error · CommandExecutionError

文字配图: 写文字 card editor did not appear after clicking "${TEXT_

Error message

文字配图: 写文字 card editor did not appear after clicking "${TEXT_IMAGE_ENTRY_LABEL}". Debug: /tmp/xhs_publish_textimage_debug.png

What it means

After clicking the 文字配图 entry, runTextImageFlow waits for the first 写文字 card editor to appear via waitForFirstCard. If it never appears, a debug screenshot is saved and this error is thrown — the entry was clicked but the editor never mounted.

Source

Thrown at clis/xiaohongshu/publish.js:1059

        await page.screenshot({ path: '/tmp/xhs_publish_media_debug.png' });
        throw new CommandExecutionError(`${label}: expected at least ${expectedCount} visible media item(s), got ${state.count}. ` +
            'Debug screenshot: /tmp/xhs_publish_media_debug.png');
    }
}
/**
 * Drive the full 文字配图 sub-flow: entry → type cards → 生成图片 → pick style → 下一步.
 * Leaves the page on the standard editor (caller then runs waitForEditForm).
 */
async function runTextImageFlow(page, cards, cardStyle) {
    const entry = await clickByText(page, TEXT_IMAGE_ENTRY_LABEL);
    if (!entry?.ok) {
        await page.screenshot({ path: '/tmp/xhs_publish_textimage_debug.png' });
        throw new CommandExecutionError(`文字配图: could not click "${TEXT_IMAGE_ENTRY_LABEL}" entry. ` +
            'Debug: /tmp/xhs_publish_textimage_debug.png');
    }
    if (!(await waitForFirstCard(page))) {
        await page.screenshot({ path: '/tmp/xhs_publish_textimage_debug.png' });
        throw new CommandExecutionError(`文字配图: 写文字 card editor did not appear after clicking "${TEXT_IMAGE_ENTRY_LABEL}". ` +
            'Debug: /tmp/xhs_publish_textimage_debug.png');
    }
    for (let i = 0; i < cards.length; i++) {
        if (i > 0) {
            const added = await addCard(page, i + 1);
            if (!added) {
                await page.screenshot({ path: '/tmp/xhs_publish_addcard_debug.png' });
                throw new CommandExecutionError(`文字配图: new card editor #${i + 1} did not render after "${ADD_CARD_LABEL}". ` +
                    'Debug: /tmp/xhs_publish_addcard_debug.png');
            }
        }
        await fillCard(page, cards[i], i);
    }
    const generated = await clickGenerate(page);
    if (!generated) {
        await page.screenshot({ path: '/tmp/xhs_publish_generate_debug.png' });
        throw new CommandExecutionError(`文字配图: "${GENERATE_LABEL}" did not advance to the 预览图片 step. ` +
            'Debug: /tmp/xhs_publish_generate_debug.png');

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Inspect /tmp/xhs_publish_textimage_debug.png to see what appeared instead of the editor.
  2. Retry the flow with longer waits; slow mounts are the most common cause.
  3. Confirm the XHS session is valid (re-login if a login dialog intercepts the flow).
  4. If XHS changed DOM, update waitForFirstCard's selectors to match the current 写文字 editor.

Example fix

// before
await runTextImageFlow(page, cards, style);
// after
try {
  await runTextImageFlow(page, cards, style);
} catch (e) {
  if (/card editor did not appear/.test(e.message)) {
    await page.wait({ time: 3.0 });
    await runTextImageFlow(page, cards, style);
  } else throw e;
}
Defensive patterns

Strategy: retry

Validate before calling

// confirm the entry was actually opened before waiting for editor
const opened = await clickByText(page, TEXT_IMAGE_ENTRY_LABEL);
if (!opened?.ok) throw new Error('entry not clicked; editor will not appear');

Type guard

null

Try / catch

try { await runTextImageFlow(page, cards, style); }
catch (e) {
  if (/card editor did not appear/.test(e.message)) {
    await page.wait({ time: 3.0 });
    await runTextImageFlow(page, cards, style);
  } else throw e;
}

Prevention

When it happens

Trigger: waitForFirstCard timed out — entry click landed but XHS didn't open the 写文字 editor (client-side error in XHS, animation/dialog blocking, or the editor renders under different selectors).

Common situations: XHS A/B change replaced the card editor markup; a rate-limit or login-expiry dialog appeared instead; very slow network exceeding the waitForFirstCard timeout; the entry click actually opened a different option (text-match collision).

Related errors


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