jackwener/OpenCLI · error · CommandExecutionError
WeChat image upload fallback failed: ${fallback?.reason || '
Error message
WeChat image upload fallback failed: ${fallback?.reason || 'unknown error'} What it means
Thrown by injectImageFile when the primary setFileInput path could not run and the fallback path — reading the image as base64 and injecting it via an in-page evaluate() upload — reports failure via { ok: false, reason }. The reason string from the in-page script is embedded in the error message.
Source
Thrown at clis/weixin/create-draft.js:148
try {
var binary = atob(${JSON.stringify(base64)});
var bytes = new Uint8Array(binary.length);
for (var i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
var transfer = new DataTransfer();
transfer.items.add(new File([bytes], ${JSON.stringify(image.fileName)}, { type: ${JSON.stringify(image.mimeType)} }));
var descriptor = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'files');
if (descriptor && descriptor.set) descriptor.set.call(input, transfer.files);
else input.files = transfer.files;
if (!input.files || input.files.length !== 1) return { ok: false, reason: 'file input rejected fallback file' };
input.dispatchEvent(new Event('input', { bubbles: true }));
input.dispatchEvent(new Event('change', { bubbles: true }));
return { ok: true };
} catch (error) {
return { ok: false, reason: String(error && error.message || error) };
}
})()`);
if (!fallback?.ok) {
throw new CommandExecutionError(`WeChat image upload fallback failed: ${fallback?.reason || 'unknown error'}`);
}
}
async function uploadContentImage(page, image) {
const previousKeys = await readCdnImageKeys(page);
const opened = await evaluate(page, `(() => {
var button = document.querySelector('#js_editor_insertimage');
if (!button) return { ok: false, reason: 'insert-image button not found' };
button.click();
return { ok: true };
})()`);
if (!opened?.ok) throw new CommandExecutionError(`Could not open WeChat image upload: ${opened?.reason || 'unknown error'}`);
await page.wait(1);
const selected = await evaluate(page, `(() => {
var item = document.querySelector('.js_img_dropdown_menu .tpl_dropdown_menu_item');
if (!item) return { ok: false, reason: 'upload menu item not found' };
item.click();View on GitHub (pinned to 49907e53dc)
Solutions
- Compress/resize the image (e.g. <1MB, JPEG/PNG) before running the command so base64 injection fits within limits.
- Ensure the upload dialog is fully open before the fallback runs (add a wait/poll for the file input).
- Inspect fallback.reason in the error message — it names the underlying in-page failure — and fix that specific cause.
- Prefer fixing the primary setFileInput path so the fragile base64 fallback is never needed.
Example fix
// before
const base64 = fs.readFileSync(image.absPath).toString('base64');
// after
const stats = fs.statSync(image.absPath);
if (stats.size > 2 * 1024 * 1024) {
image.absPath = await compressImage(image.absPath, { maxBytes: 2 * 1024 * 1024 });
}
const base64 = fs.readFileSync(image.absPath).toString('base64'); Defensive patterns
Strategy: validation
Validate before calling
const fs = require('fs');
const MAX = 2 * 1024 * 1024;
const size = fs.statSync(image.absPath).size;
if (size > MAX) throw new Error(`image too large for base64 fallback (${size} bytes); compress below 2MB`);
if (!/\.(jpe?g|png|gif)$/i.test(image.absPath)) throw new Error('convert image to JPEG/PNG/GIF before upload'); Type guard
function isUploadResult(v) { return typeof v === 'object' && v !== null && typeof v.ok === 'boolean'; } Try / catch
try {
await createDraftCommand(opts);
} catch (e) {
if (/image upload fallback failed/i.test(e.message)) {
console.error('fallback reason:', e.message); // reason names the in-page failure
}
throw e;
} Prevention
- Compress images below ~1–2MB so base64 injection stays within evaluate limits.
- Convert to JPEG/PNG before uploading.
- Ensure the upload dialog and file input exist before the fallback runs.
- Fix the primary setFileInput path so the fragile base64 fallback is rarely used.
When it happens
Trigger: The base64 image is too large for the evaluate bridge or the page, the in-page script cannot find the file input to populate, the page context threw (input missing, dialog closed, CSP or driver restrictions on large strings), or the image is not a format WeChat accepts.
Common situations: Very large images (multi-MB) blowing up evaluate string limits; base64 fallback running before the upload dialog opened; driver restrictions on evaluating large payloads; image format issues (e.g. webp) rejected by the page script.
Related errors
- WeChat image upload failed: ${message}
- WeChat image upload failed: ${state.errorText}
- WeChat image upload timed out before a new CDN image appeare
- Failed to attach file
- Failed to read image dimensions for ${filePath}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/883d2fb542660f6f.
Report an issue: GitHub.