jackwener/OpenCLI · error · CommandExecutionError
Appending images failed: ${upload.error ?? 'unknown'}. Debug
Error message
Appending images failed: ${upload.error ?? 'unknown'}. Debug screenshot: /tmp/xhs_publish_append_debug.png What it means
In 文字配图 (text-image) mode, after generated cards are applied, any additional --images files are appended via uploadImages. If that append upload fails, the CLI screenshots the page and aborts with the underlying upload error.
Source
Thrown at clis/xiaohongshu/publish.js:1265
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 ─────────────────────────────────────────────────────
await fillField(page, TITLE_SELECTORS, title, 'title');
await page.wait({ time: 0.5 });
// ── Step 5: Fill content / body ────────────────────────────────────────────
await fillField(page, BODY_SELECTORS, content, 'content');
await page.wait({ time: 0.5 });
// ── Step 6: Add topic hashtags ─────────────────────────────────────────────
// XHS converts a "#keyword" typed into the body editor into a real topic
// entity only when the user picks an item from the inline suggestion
// dropdown that pops up while typing. The previous implementation looked
// for a standalone "添加话题" button + dedicated search <input>, which the
// current creator-center editor no longer exposes — it left bare "#"View on GitHub (pinned to 49907e53dc)
Solutions
- Read the upload.error detail and check /tmp/xhs_publish_append_debug.png.
- Verify each appended image path exists, is absolute, and is a supported format.
- Retry the command; transient injection races occur.
- If only generated cards are needed, drop the --images flag to bypass the append step.
Example fix
// before opencli xiaohongshu publish --text-image --images missing.png // after ls -l missing.png # verify first, or omit --images to use generated cards only
Defensive patterns
Strategy: validation
Validate before calling
const fs = require('fs');
const appendPaths = opts.images || [];
for (const p of appendPaths) {
if (!fs.existsSync(p)) throw new Error(`Append image not found: ${p}`);
} Try / catch
try {
await publish({ textImage: true, images: extra });
} catch (e) {
if (String(e.message).startsWith('Appending images failed')) {
// fall back to generated cards only
return publish({ textImage: true });
}
throw e;
} Prevention
- Verify appended image paths exist and are absolute before invoking.
- Use supported image formats for appended files.
- If extra uploads aren't essential, omit --images in text-image mode.
- Check /tmp/xhs_publish_append_debug.png for recurring failures.
When it happens
Trigger: isTextImage is true and absImagePaths.length > 0, and the second uploadImages call returns { ok:false } — file missing/unreadable, input selector changed, or injection rejected.
Common situations: Same causes as the initial upload error: bad/relative image paths, unsupported format, deleted files, or composer DOM changes — but hit only when combining generated cards with extra uploaded images.
Related errors
- Image injection failed: ${upload.error ?? 'unknown'}. Debug
- Failed to attach file
- Instagram fallback file injection failed
- Mercury reimbursement-draft requires Browser Bridge uploadFi
- Mercury receipt upload did not confirm exactly one uploaded
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/0b85521602386630.
Report an issue: GitHub.