jackwener/OpenCLI · error · CommandExecutionError

WeChat uploaded the image but did not confirm it as the draf

Error message

WeChat uploaded the image but did not confirm it as the draft cover.

What it means

This CommandExecutionError is thrown when selectCoverFromContent() does not return exactly true after the cover image was uploaded into the article body. The flow uploads the image via uploadContentImage(), then asks WeChat to set it as the draft cover; any non-true result (timeout, dialog not found, WeChat UI change) produces this error. Unlike the fill errors, the upload itself succeeded — only the cover-selection confirmation failed.

Source

Thrown at clis/weixin/create-draft.js:310

    func: async (page, kwargs) => {
        try {
            const coverImage = kwargs['cover-image'] ? resolveCoverImage(kwargs['cover-image']) : null;
            await navigateToEditor(page);

            const titleResult = await fillField(page, 'textarea#title', kwargs.title);
            if (!titleResult?.ok) throw new CommandExecutionError('Failed to fill title');
            if (kwargs.author) {
                const authorResult = await fillField(page, 'input#author', kwargs.author);
                if (!authorResult?.ok) throw new CommandExecutionError('Failed to fill author');
            }
            const contentResult = await fillContent(page, kwargs.content);
            if (!contentResult?.ok) throw new CommandExecutionError('Failed to fill content');

            if (coverImage) {
                await uploadContentImage(page, coverImage);
                const coverSet = await selectCoverFromContent(page);
                if (coverSet !== true) {
                    throw new CommandExecutionError('WeChat uploaded the image but did not confirm it as the draft cover.');
                }
            }

            if (kwargs.summary) {
                const summaryResult = await fillField(page, 'textarea#js_description', kwargs.summary);
                if (!summaryResult?.ok) throw new CommandExecutionError('Failed to fill summary');
            }

            await saveDraft(page);
            return [{
                status: 'draft saved',
                detail: `"${kwargs.title}"${kwargs.author ? ` by ${kwargs.author}` : ''}${coverImage ? ' (with cover)' : ''}`,
            }];
        } catch (error) {
            if (error instanceof CliError) throw error;
            const message = error instanceof Error ? error.message : String(error);
            throw new CommandExecutionError(`WeChat create-draft failed: ${message}`);
        }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-run with a standard JPEG/PNG cover sized to WeChat's recommended cover ratio (~2.35:1, e.g., 900x383) — dimension/format rejection is a frequent silent cause.
  2. Retry once — slow image upload racing the cover-selection step often resolves on a second attempt.
  3. Inspect selectCoverFromContent() in clis/weixin/create-draft.js against the live editor UI; update its dialog selectors if WeChat changed the cover flow.
  4. Drop --cover-image and set the cover manually in the WeChat web UI to unblock draft creation, then fix the automation.

Example fix

// before
const coverSet = await selectCoverFromContent(page);
if (coverSet !== true) {
    throw new CommandExecutionError('WeChat uploaded the image but did not confirm it as the draft cover.');
}
// after
const coverSet = await selectCoverFromContent(page);
if (coverSet !== true) {
    throw new CommandExecutionError(`Cover upload succeeded but cover selection returned ${JSON.stringify(coverSet)}; check selectCoverFromContent selectors and image dimensions (WeChat requires ~2.35:1).`);
}
Defensive patterns

Strategy: try-catch

Validate before calling

const stat = fs.statSync(coverPath);
const isImage = /\.(jpe?g|png|gif|webp)$/i.test(coverPath);
// additionally keep dimensions near WeChat's ~2.35:1 cover ratio
if (!stat.isFile() || !isImage) throw new Error('Cover must be an existing JPEG/PNG/GIF/WebP file, ideally ~2.35:1 (e.g. 900x383).');

Type guard

function isUsableCover(p) {
  return typeof p === 'string' && p.length > 0 && /\.(jpe?g|png|gif|webp)$/i.test(p);
}

Try / catch

try {
  await createDraft({ title, content, coverImage });
} catch (e) {
  if (e instanceof CommandExecutionError && /did not confirm it as the draft cover/.test(e.message)) {
    // fallback: create the draft without the cover, or retry with a differently sized JPEG
  } else throw e;
}

Prevention

When it happens

Trigger: Passing --cover-image where uploadContentImage succeeds but selectCoverFromContent returns false/undefined: the cover-selection dialog did not open or confirm within its timeouts, WeChat changed the 'set as cover' UI flow, the uploaded image did not appear in the editor (CDN key scan found nothing), or WeChat silently rejected the image format/dimensions.

Common situations: WeChat A/B tests a new cover-picker dialog so selectCoverFromContent's selectors no longer match; image fails WeChat's cover aspect-ratio/size requirements so the confirm step is skipped; slow CDN upload races the selection step; GIF/WebP covers rejected by a server-side rule despite local MIME validation passing.

Related errors


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