jackwener/OpenCLI · error · CommandExecutionError

Editing form did not appear after image acquisition. The pag

Error message

Editing form did not appear after image acquisition. The page layout may have changed. Debug screenshot: /tmp/xhs_publish_form_debug.png

What it means

After images are acquired/uploaded, the CLI waits for the note editor form (title/description fields) via waitForEditForm. If the form never appears, the page structure no longer matches expectations and the publish flow cannot continue, so it aborts with a debug screenshot.

Source

Thrown at clis/xiaohongshu/publish.js:1254

        if (isTextImage) {
            // Drive 文字配图: type cards → 生成图片 → pick style → 下一步 → standard editor.
            appliedCardStyle = await runTextImageFlow(page, cards, cardStyle);
        }
        else {
            const upload = await uploadImages(page, absImagePaths);
            if (!upload.ok) {
                await page.screenshot({ path: '/tmp/xhs_publish_upload_debug.png' });
                throw new CommandExecutionError(`Image injection failed: ${upload.error ?? 'unknown'}. ` +
                    'Debug screenshot: /tmp/xhs_publish_upload_debug.png');
            }
            await page.wait({ time: UPLOAD_SETTLE_MS / 1_000 });
            await waitForUploads(page);
        }
        // ── Step 3b: Wait for editor form to render ───────────────────────────────
        const formReady = await waitForEditForm(page);
        if (!formReady) {
            await page.screenshot({ path: '/tmp/xhs_publish_form_debug.png' });
            throw new CommandExecutionError('Editing form did not appear after image acquisition. The page layout may have changed. ' +
                'Debug screenshot: /tmp/xhs_publish_form_debug.png');
        }
        if (isTextImage) {
            await assertComposerMediaCount(page, cards.length, '文字配图 generated images');
        }
        // ── Step 3c: In text-image mode, optionally append uploaded images ────────
        if (isTextImage && absImagePaths.length > 0) {
            const upload = await uploadImages(page, absImagePaths);
            if (!upload.ok) {
                await page.screenshot({ path: '/tmp/xhs_publish_append_debug.png' });
                throw new CommandExecutionError(`Appending images failed: ${upload.error ?? 'unknown'}. ` +
                    'Debug screenshot: /tmp/xhs_publish_append_debug.png');
            }
            await page.wait({ time: UPLOAD_SETTLE_MS / 1_000 });
            await waitForUploads(page);
            await assertComposerMediaCount(page, cards.length + absImagePaths.length, '文字配图 appended images');
        }
        // ── Step 4: Fill title ─────────────────────────────────────────────────────

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Inspect /tmp/xhs_publish_form_debug.png to see what the page actually shows.
  2. Retry — slow rendering can exceed the wait timeout.
  3. Check the screenshot for login/verification dialogs and re-capture login if present.
  4. Update the CLI or report the issue if the editor DOM changed.
Defensive patterns

Strategy: retry

Try / catch

try {
  await publish(opts);
} catch (e) {
  if (String(e.message).includes('Editing form did not appear')) {
    await sleep(5000); // allow slow render
    return publish(opts);
  }
  throw e;
}

Prevention

When it happens

Trigger: waitForEditForm returns false after upload — the editor form did not render within its wait window after successful image injection.

Common situations: Xiaohongshu redesigned the editor so the form selectors no longer match, a previous step silently failed leaving a modal/error dialog open, slow network kept the form from rendering in time, or the session was downgraded mid-flow.

Related errors


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