{"record":{"id":"883d2fb542660f6f","repo":"jackwener/OpenCLI","slug":"wechat-image-upload-fallback-failed-fallback-r","errorCode":null,"errorMessage":"WeChat image upload fallback failed: ${fallback?.reason || 'unknown error'}","messagePattern":"WeChat image upload fallback failed: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/weixin/create-draft.js","lineNumber":148,"sourceCode":"        try {\n            var binary = atob(${JSON.stringify(base64)});\n            var bytes = new Uint8Array(binary.length);\n            for (var i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n            var transfer = new DataTransfer();\n            transfer.items.add(new File([bytes], ${JSON.stringify(image.fileName)}, { type: ${JSON.stringify(image.mimeType)} }));\n            var descriptor = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'files');\n            if (descriptor && descriptor.set) descriptor.set.call(input, transfer.files);\n            else input.files = transfer.files;\n            if (!input.files || input.files.length !== 1) return { ok: false, reason: 'file input rejected fallback file' };\n            input.dispatchEvent(new Event('input', { bubbles: true }));\n            input.dispatchEvent(new Event('change', { bubbles: true }));\n            return { ok: true };\n        } catch (error) {\n            return { ok: false, reason: String(error && error.message || error) };\n        }\n    })()`);\n    if (!fallback?.ok) {\n        throw new CommandExecutionError(`WeChat image upload fallback failed: ${fallback?.reason || 'unknown error'}`);\n    }\n}\n\nasync function uploadContentImage(page, image) {\n    const previousKeys = await readCdnImageKeys(page);\n    const opened = await evaluate(page, `(() => {\n        var button = document.querySelector('#js_editor_insertimage');\n        if (!button) return { ok: false, reason: 'insert-image button not found' };\n        button.click();\n        return { ok: true };\n    })()`);\n    if (!opened?.ok) throw new CommandExecutionError(`Could not open WeChat image upload: ${opened?.reason || 'unknown error'}`);\n    await page.wait(1);\n\n    const selected = await evaluate(page, `(() => {\n        var item = document.querySelector('.js_img_dropdown_menu .tpl_dropdown_menu_item');\n        if (!item) return { ok: false, reason: 'upload menu item not found' };\n        item.click();","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/weixin/create-draft.js#L130-L166","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst base64 = fs.readFileSync(image.absPath).toString('base64');\n// after\nconst stats = fs.statSync(image.absPath);\nif (stats.size > 2 * 1024 * 1024) {\n    image.absPath = await compressImage(image.absPath, { maxBytes: 2 * 1024 * 1024 });\n}\nconst base64 = fs.readFileSync(image.absPath).toString('base64');","handlingStrategy":"validation","validationCode":"const fs = require('fs');\nconst MAX = 2 * 1024 * 1024;\nconst size = fs.statSync(image.absPath).size;\nif (size > MAX) throw new Error(`image too large for base64 fallback (${size} bytes); compress below 2MB`);\nif (!/\\.(jpe?g|png|gif)$/i.test(image.absPath)) throw new Error('convert image to JPEG/PNG/GIF before upload');","typeGuard":"function isUploadResult(v) { return typeof v === 'object' && v !== null && typeof v.ok === 'boolean'; }","tryCatchPattern":"try {\n    await createDraftCommand(opts);\n} catch (e) {\n    if (/image upload fallback failed/i.test(e.message)) {\n        console.error('fallback reason:', e.message); // reason names the in-page failure\n    }\n    throw e;\n}","preventionTips":["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."],"tags":["wechat","file-upload","base64","image"],"backgroundTag":"file-upload-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}