jackwener/OpenCLI · error · CommandExecutionError
文字配图: card editor #${index + 1} is empty after typing
Error message
文字配图: card editor #${index + 1} is empty after typing What it means
After typing text into a card editor, fillCard reads back the editor content via activeCardText and throws if the read reports not-ok/empty — i.e. the typed text did not land in the editor.
Source
Thrown at clis/xiaohongshu/publish.js:904
const focused = await focusActiveCard(page);
if (!focused?.ok)
throw new CommandExecutionError(`文字配图: could not focus card editor #${index + 1}`);
if (typeof page.insertText === 'function') {
const lines = text.split('\n');
for (let i = 0; i < lines.length; i++) {
if (i > 0 && typeof page.pressKey === 'function')
await page.pressKey('Enter');
if (lines[i])
await page.insertText(lines[i]);
}
}
else {
await page.evaluate(`(t => document.execCommand('insertText', false, t))(${JSON.stringify(text)})`);
}
await page.wait({ time: 0.4 });
const state = await activeCardText(page);
if (!state?.ok)
throw new CommandExecutionError(`文字配图: card editor #${index + 1} is empty after typing`);
}
/**
* On the 预览图片 step, optionally pick a style. The style picker is a
* scrollable strip whose options are loaded lazily, so we scroll it to the end
* to surface every option, then read the real on-page labels (no hard-coded
* whitelist — XHS adds/removes styles over time). The strip is located by
* anchoring on a known seed label (e.g. 基础) rather than a volatile class name.
*
* If the caller requested a style, it is a write-side postcondition: either
* that style is available and clicked, or publishing fails before submit.
*/
async function selectCardStyle(page, styleName) {
if (!styleName || styleName === DEFAULT_CARD_STYLE)
return DEFAULT_CARD_STYLE; // default 基础 is preselected — nothing to do.
// The style strip (".cover-list-container") is VIRTUALIZED: only the items
// near the viewport are in the DOM, so a single read sees ~10 of ~20 options
// and an option scrolled out of view cannot be clicked. Step-scroll the strip
// (".cover-list-container-wrapper"), accumulating every label seen; stop asView on GitHub (pinned to 49907e53dc)
Solutions
- Re-run the flow; focus loss races are usually transient.
- Ensure the page wrapper exposes insertText and pressKey so the primary typing path is used instead of execCommand.
- Increase the post-type wait (the code waits 0.4s) by retrying with slower pacing.
- If persistent, update activeCardText selectors — XHS DOM likely changed.
Example fix
// before
await fillCard(page, "line1\nline2", 0);
// after
try {
await fillCard(page, "line1\nline2", 0);
} catch (e) {
if (/is empty after typing/.test(e.message)) {
await fillCard(page, "line1\nline2", 0); // retry once after refocus
} else throw e;
} Defensive patterns
Strategy: retry
Validate before calling
if (typeof page.insertText !== 'function' && typeof page.pressKey !== 'function') console.warn('typing support limited; multi-line cards may fail'); Type guard
null
Try / catch
try { await fillCard(page, text, i); }
catch (e) {
if (/is empty after typing/.test(e.message)) {
await fillCard(page, text, i); // refocus-and-retype once
} else throw e;
} Prevention
- Ensure insertText/pressKey are implemented on the page wrapper
- Keep card text short enough to type in one pass without overlays
- Verify content after typing and retype on empty reads
When it happens
Trigger: insertText (or execCommand insertText fallback) silently did nothing: editor lost focus between focus and insert, the editor is not a contenteditable, or the verification read happened before text rendered (0.4s wait insufficient).
Common situations: Card content emptied because a XHS overlay/popover stole focus mid-type; multi-line text with page.pressKey unavailable for Enter; XHS replaced its editor implementation so insertText no longer works; card editor re-rendered and cleared input.
Related errors
- Gmail ${operation} could not set the search query exactly
- ${name} menu item was clicked, but the conversation did not
- composer fill was not verified
- Midjourney ${slotLabel} reference assignment was not verifie
- Could not verify Midjourney ${anchorText}: expected ${target
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/f781a94979bbdef9.
Report an issue: GitHub.