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 as

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-run the flow; focus loss races are usually transient.
  2. Ensure the page wrapper exposes insertText and pressKey so the primary typing path is used instead of execCommand.
  3. Increase the post-type wait (the code waits 0.4s) by retrying with slower pacing.
  4. 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

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


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