{"record":{"id":"6eba499fb0f0c4a0","repo":"jackwener/OpenCLI","slug":"instagram-reel-preview-did-not-appear-after-upload","errorCode":null,"errorMessage":"Instagram reel preview did not appear after upload","messagePattern":"Instagram reel preview did not appear after upload","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/instagram/reel.js","lineNumber":220,"sourceCode":"    if (result?.count === null || result?.count === undefined)\n        return null;\n    return Number(result.count);\n}\nasync function waitForVideoPreview(page, maxWaitSeconds = 20) {\n    let lastDetail = '';\n    for (let attempt = 0; attempt < maxWaitSeconds * 2; attempt += 1) {\n        const result = await page.evaluate(buildInspectUploadStageJs());\n        lastDetail = String(result?.detail || '').trim();\n        if (result?.state === 'preview')\n            return;\n        if (result?.state === 'failed') {\n            throw new CommandExecutionError('Instagram reel upload failed', result.detail ? `Instagram rejected the reel upload: ${result.detail}` : 'Instagram rejected the reel upload before the preview stage');\n        }\n        if (attempt < maxWaitSeconds * 2 - 1)\n            await page.wait({ time: 0.5 });\n    }\n    await page.screenshot({ path: '/tmp/instagram_reel_preview_debug.png' });\n    throw new CommandExecutionError('Instagram reel preview did not appear after upload', lastDetail\n        ? `Inspect /tmp/instagram_reel_preview_debug.png. Last visible dialog text: ${lastDetail}`\n        : 'Inspect /tmp/instagram_reel_preview_debug.png for the upload state');\n}\nasync function clickAction(page, labels, scope = 'any') {\n    const result = await page.evaluate(buildClickActionJs(labels, scope));\n    if (!result?.ok) {\n        throw new CommandExecutionError(`Instagram action button not found: ${labels.join(' / ')}`);\n    }\n    return result.label || labels[0] || '';\n}\nasync function clickActionMaybe(page, labels, scope = 'any') {\n    const result = await page.evaluate(buildClickActionJs(labels, scope));\n    return !!result?.ok;\n}\nfunction buildInspectReelStageJs() {\n    return `\n    (() => {\n      const isVisible = (el) => {","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/instagram/reel.js#L202-L238","documentation":"waitForVideoPreview waits up to maxWaitSeconds*2 half-second polls for the upload to reach the 'preview' DOM state. When the loop exhausts without success, it captures a debug screenshot to /tmp/instagram_reel_preview_debug.png and throws this timeout error with the last visible dialog text. It means the upload never failed explicitly but also never reached the preview stage in time.","triggerScenarios":"All polling attempts in waitForVideoPreview complete while buildInspectUploadStageJs() keeps returning a non-'preview', non-'failed' state (e.g. still uploading, stuck progress bar, unexpected UI).","commonSituations":"Very large or slow-to-upload video exceeding maxWaitSeconds on slow connections; Instagram A/B UI changes so the preview selector no longer matches; a hidden captcha/2FA/consent dialog blocking progression; heavy page load starving the upload.","solutions":["Open /tmp/instagram_reel_preview_debug.png — it shows the actual page state at timeout.","Increase maxWaitSeconds for large files or slow networks so polling outlasts the real upload time.","If the screenshot shows a captcha/login/consent dialog, resolve that session issue; refresh cookies or re-login.","Update the stage-detection selectors in buildInspectUploadStageJs to match the current Instagram DOM.","Retry the upload; transient stalls often succeed on a second attempt."],"exampleFix":"// before\nawait waitForVideoPreview(page, 20); // 20s too short for 500MB upload\n// after\nawait waitForVideoPreview(page, 120); // allow slow uploads to finish","handlingStrategy":"retry","validationCode":"// Sanity-check budget before waiting: estimate upload time\nconst sizeMb = fs.statSync(videoPath).size / 1e6;\nconst estSeconds = sizeMb / (uplinkMbps / 8);\nconst maxWaitSeconds = Math.max(30, Math.ceil(estSeconds * 2));","typeGuard":"function isStillUploading(r) {\n  return !!r && typeof r === 'object' && r.state !== 'preview' && r.state !== 'failed';\n}","tryCatchPattern":"try {\n  await waitForVideoPreview(page, maxWaitSeconds);\n} catch (err) {\n  if (String(err.message).includes('preview did not appear')) {\n    // Screenshot already saved at /tmp/instagram_reel_preview_debug.png — inspect it,\n    // handle any blocking dialog, then retry the upload\n  } else throw err;\n}","preventionTips":["Open /tmp/instagram_reel_preview_debug.png on every occurrence before changing code","Scale maxWaitSeconds to file size and connection speed","Keep stage-detection selectors updated against current Instagram DOM","Clear unexpected dialogs (captcha/login/consent) before starting the flow"],"tags":["instagram","timeout","upload","puppeteer","automation"],"backgroundTag":"upload-timeout","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}