jackwener/OpenCLI · error · CommandExecutionError
WeChat image upload failed: ${state.errorText}
Error message
WeChat image upload failed: ${state.errorText} What it means
Thrown by uploadContentImage during the post-upload polling loop when the page reports an error text (errorText) matching WeChat's known upload failure patterns (无法解析/cannot parse, 上传失败/upload failed, 过大/too large, 频繁/too frequent, 不支持/unsupported, 错误/error). The raw WeChat error text is embedded in the message.
Source
Thrown at clis/weixin/create-draft.js:190
for (let attempt = 0; attempt < 15; attempt++) {
await page.wait(2);
const state = await evaluate(page, `(() => {
var previous = new Set(${JSON.stringify(previousKeys)});
var editor = document.querySelector('#ueditor_0');
var images = editor ? Array.from(editor.querySelectorAll('img')) : [];
var key = images.map(function(img) {
return img.getAttribute('data-src') || img.getAttribute('src') || '';
}).find(function(src) { return /(?:mmbiz|qpic\\.cn)/i.test(src) && !previous.has(src); });
var errorText = Array.from(document.querySelectorAll('.weui-desktop-tips, .weui-desktop-toast, .js_msgSenderTips'))
.filter(function(el) { return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length); })
.map(function(el) { return (el.innerText || el.textContent || '').trim(); })
.filter(Boolean).join('\\n');
return { ok: !!key, errorText: errorText };
})()`);
if (state?.ok) return;
if (state?.errorText && /(无法解析|上传失败|过大|频繁|不支持|错误)/.test(state.errorText)) {
throw new CommandExecutionError(`WeChat image upload failed: ${state.errorText}`);
}
}
throw new CommandExecutionError('WeChat image upload timed out before a new CDN image appeared in the editor.');
}
async function selectCoverFromContent(page) {
await evaluate(page, 'document.querySelector("#js_cover_description_area")?.scrollIntoView()');
await page.wait(1);
await evaluate(page, 'document.querySelector(".js_cover_btn_area")?.click()');
await page.wait(1);
await evaluate(page, `(() => {
var link = Array.from(document.querySelectorAll('a.pop-opr__button')).find(function(el) {
return (el.textContent || '').trim() === '从正文选择';
});
if (link) link.click();
})()`);
await page.wait(2);
await evaluate(page, `document.querySelector('.weui-desktop-dialog_img-picker .appmsg_content_img')?.click()`);View on GitHub (pinned to 49907e53dc)
Solutions
- Read the embedded WeChat error text: resize/compress the image if it says 过大, convert to JPEG/PNG if 不支持, or wait before retrying if 频繁.
- Validate the image file locally (size, format, integrity) before running the command.
- Add a delay/backoff between uploads or between command runs to avoid WeChat's rate limit.
- Retry once after a pause if the error text indicates a transient server-side 错误.
Example fix
// before
await uploadContentImage(page, image);
// after
const stats = fs.statSync(image.absPath);
if (stats.size > 10 * 1024 * 1024) {
image.absPath = await compressImage(image.absPath, { maxBytes: 10 * 1024 * 1024, format: 'jpeg' });
}
await sleep(5000); // avoid 频繁 rate limit
await uploadContentImage(page, image); Defensive patterns
Strategy: validation
Validate before calling
const fs = require('fs');
const MAX_BYTES = 10 * 1024 * 1024;
const size = fs.statSync(image.absPath).size;
if (size > MAX_BYTES) throw new Error(`image ${image.absPath} is ${size} bytes; WeChat limit exceeded — compress first`);
if (!/\.(jpe?g|png|gif)$/i.test(image.absPath)) throw new Error('unsupported format; convert to JPEG/PNG/GIF'); Type guard
function isUploadState(v) { return typeof v === 'object' && v !== null && ('ok' in v) && ('errorText' in v); } Try / catch
try {
await createDraftCommand(opts);
} catch (e) {
if (/WeChat image upload failed: (.+)/.test(e.message)) {
const wechatError = e.message.match(/WeChat image upload failed: (.+)/)[1];
if (/频繁/.test(wechatError)) { await sleep(60000); /* retry after rate limit */ }
else if (/过大|不支持|无法解析/.test(wechatError)) { /* fix image locally before retry */ }
}
throw e;
} Prevention
- Pre-compress images well under WeChat's size limit.
- Convert all images to JPEG/PNG before upload.
- Throttle command runs to avoid WeChat's 频繁 rate limit.
- Parse the embedded Chinese error text to choose the right remediation.
When it happens
Trigger: The uploaded image exceeds WeChat's size limit (过大), the image format is unsupported (不支持), uploads are rate-limited (频繁), the image cannot be parsed (无法解析), or WeChat's upload endpoint returned an error shown in the dialog.
Common situations: Uploading images over ~10MB or with unsupported formats (BMP, very large PNGs); batch-running the command many times in a row triggering rate limiting; corrupted or zero-byte image files; temporary WeChat server-side upload errors.
Related errors
- WeChat image upload failed: ${message}
- WeChat image upload fallback failed: ${fallback?.reason || '
- WeChat image upload timed out before a new CDN image appeare
- API_ERROR
- API_ERROR
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/87f1679a3be74172.
Report an issue: GitHub.