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
- Inspect /tmp/xhs_publish_textimage_debug.png to see what appeared instead of the editor.
- Retry the flow with longer waits; slow mounts are the most common cause.
- Confirm the XHS session is valid (re-login if a login dialog intercepts the flow).
- 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
- Ensure a valid XHS session (login dialogs block the editor from mounting)
- Allow generous timeouts for slow networks
- Inspect the debug screenshot to see what rendered instead
- Keep waitForFirstCard selectors current with XHS DOM changes
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
- Unexpected 12306 probe: ${JSON.stringify(probe)}
- ChatGPT did not create a conversation URL after sending the
- ChatWise response
- Could not switch to ${wantModel} model
- No Claude response appeared within ${timeoutSeconds}s. Re-ru
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/8feed5ccd1228a89.
Report an issue: GitHub.