{"record":{"id":"0deac440f3f2c9cc","repo":"jackwener/OpenCLI","slug":"image-upload-did-not-complete-before-timeout","errorCode":null,"errorMessage":"Image upload did not complete before timeout","messagePattern":"Image upload did not complete before timeout","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/weibo/publish.js","lineNumber":196,"sourceCode":"            // Wait for upload to complete\n            let uploadResult = null;\n            for (let i = 0; i < Math.ceil(UPLOAD_TIMEOUT_MS / UPLOAD_POLL_MS); i++) {\n                await page.wait({ time: UPLOAD_POLL_MS / 1000 });\n                uploadResult = await page.evaluateWithArgs(`\n                    (() => {\n                        const expectedCount = expected;\n                        const uploading = document.querySelector('[class*=\"upload\"], [class*=\"progress\"]');\n                        if (uploading && uploading.offsetParent !== null) return null;\n                        const pics = document.querySelectorAll('img[class*=\"pic\"], [class*=\"imgItem\"], [class*=\"picture\"] img');\n                        if (pics.length >= expectedCount) return { ok: true, count: pics.length };\n                        return null;\n                    })()\n                `, { expected: absPaths.length });\n                if (uploadResult !== null) break;\n            }\n\n            if (!uploadResult?.ok) {\n                throw new CommandExecutionError(uploadResult?.message ?? 'Image upload did not complete before timeout');\n            }\n        }\n\n        // Step 6: Insert text using native DOM setter (preserves Weibo internal state)\n        // IMPORTANT: Using nativeSetter preserves the textarea's reactive/internal state.\n        // Direct ta.value= assignment bypasses Weibo's Vue reactivity and causes \"undefined\" content.\n        const insertResult = await page.evaluateWithArgs(`\n            ((selectors) => {\n                let ta = null;\n                for (const sel of selectors) {\n                    for (const t of document.querySelectorAll(sel)) {\n                        if (t.offsetParent !== null) ta = t;\n                    }\n                }\n                if (!ta) return { ok: false, message: 'textarea not visible' };\n                ta.focus();\n                const nativeSetter = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'value')?.set;\n                if (nativeSetter) {","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/weibo/publish.js#L178-L214","documentation":"Thrown when the image upload either never finished within UPLOAD_TIMEOUT_MS (30s, polled every 1.5s) or the page's own polling code reported a failure via uploadResult.message. The command waits for Weibo to confirm all uploaded images (expected count = absPaths.length) before inserting text and publishing.","triggerScenarios":"page.evaluate poll loop returns uploadResult that is null/ok:false, or keeps returning null until the poll budget expires; then `uploadResult?.ok` is falsy and this error is raised with uploadResult.message or the fallback text.","commonSituations":"Slow or proxied network where a large image takes >30s to upload to Weibo's CDN; Weibo rate-limiting or rejecting an image (size, dimensions); the file input accepted files but Weibo's uploader hit a client-side error; too many images at once (up to 9).","solutions":["Retry the publish — transient network slowness is the most common cause","Reduce image count and/or use smaller/compressed images so uploads finish within 30s","Check the accompanying uploadResult.message for Weibo's specific rejection reason and fix that (e.g. image too large)","Verify the images load and are valid jpg/png/gif/webp before invoking"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"for (const p of paths) {\n    const stat = fs.statSync(p, { throwIfNoEntry: false });\n    if (!stat || stat.size > 5 * 1024 * 1024) {\n        console.warn(`${p} is missing or larger than 5MB — upload may time out`);\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    await publishToWeibo(text, images);\n} catch (err) {\n    if (String(err.message).includes('upload did not complete')) {\n        await new Promise(r => setTimeout(r, 5000));\n        await publishToWeibo(text, images); // one retry\n    } else throw err;\n}","preventionTips":["Compress images before uploading so each finishes well within 30s","Limit to 1–4 images for automations over slow links","Avoid running publishes over high-latency proxies/VPNs","Check image validity (correct extension, non-zero size) beforehand"],"tags":["upload-timeout","network","weibo"],"backgroundTag":"upload-timeout","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}