jackwener/OpenCLI · error · CommandExecutionError

Image upload did not complete before timeout

Error message

Image upload did not complete before timeout

What it means

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.

Source

Thrown at clis/weibo/publish.js:196

            // Wait for upload to complete
            let uploadResult = null;
            for (let i = 0; i < Math.ceil(UPLOAD_TIMEOUT_MS / UPLOAD_POLL_MS); i++) {
                await page.wait({ time: UPLOAD_POLL_MS / 1000 });
                uploadResult = await page.evaluateWithArgs(`
                    (() => {
                        const expectedCount = expected;
                        const uploading = document.querySelector('[class*="upload"], [class*="progress"]');
                        if (uploading && uploading.offsetParent !== null) return null;
                        const pics = document.querySelectorAll('img[class*="pic"], [class*="imgItem"], [class*="picture"] img');
                        if (pics.length >= expectedCount) return { ok: true, count: pics.length };
                        return null;
                    })()
                `, { expected: absPaths.length });
                if (uploadResult !== null) break;
            }

            if (!uploadResult?.ok) {
                throw new CommandExecutionError(uploadResult?.message ?? 'Image upload did not complete before timeout');
            }
        }

        // Step 6: Insert text using native DOM setter (preserves Weibo internal state)
        // IMPORTANT: Using nativeSetter preserves the textarea's reactive/internal state.
        // Direct ta.value= assignment bypasses Weibo's Vue reactivity and causes "undefined" content.
        const insertResult = await page.evaluateWithArgs(`
            ((selectors) => {
                let ta = null;
                for (const sel of selectors) {
                    for (const t of document.querySelectorAll(sel)) {
                        if (t.offsetParent !== null) ta = t;
                    }
                }
                if (!ta) return { ok: false, message: 'textarea not visible' };
                ta.focus();
                const nativeSetter = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'value')?.set;
                if (nativeSetter) {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry the publish — transient network slowness is the most common cause
  2. Reduce image count and/or use smaller/compressed images so uploads finish within 30s
  3. Check the accompanying uploadResult.message for Weibo's specific rejection reason and fix that (e.g. image too large)
  4. Verify the images load and are valid jpg/png/gif/webp before invoking
Defensive patterns

Strategy: retry

Validate before calling

for (const p of paths) {
    const stat = fs.statSync(p, { throwIfNoEntry: false });
    if (!stat || stat.size > 5 * 1024 * 1024) {
        console.warn(`${p} is missing or larger than 5MB — upload may time out`);
    }
}

Try / catch

try {
    await publishToWeibo(text, images);
} catch (err) {
    if (String(err.message).includes('upload did not complete')) {
        await new Promise(r => setTimeout(r, 5000));
        await publishToWeibo(text, images); // one retry
    } else throw err;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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).

Understand the failure class

Related errors


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