{"record":{"id":"20ec97a3e23ccf1d","repo":"jackwener/OpenCLI","slug":"failed-to-open-instagram-post-composer","errorCode":null,"errorMessage":"Failed to open Instagram post composer","messagePattern":"Failed to open Instagram post composer","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/instagram/post.js","lineNumber":315,"sourceCode":"                }\n                catch {\n                    // Best-effort: a fresh automation window is safer than reusing a polluted one.\n                }\n            }\n            if (!resetWindow) {\n                await dismissResidualDialogs(input.page);\n                await input.page.wait({ time: 1 });\n            }\n        }\n    }\n    throw lastError instanceof Error ? lastError : new CommandExecutionError('Instagram post failed');\n}\nasync function ensureComposerOpen(page) {\n    const result = await page.evaluate(buildEnsureComposerOpenJs());\n    if (!result?.ok) {\n        if (result?.reason === 'auth')\n            throw new AuthRequiredError('www.instagram.com', 'Instagram login required before posting');\n        throw new CommandExecutionError('Failed to open Instagram post composer');\n    }\n}\nasync function dismissResidualDialogs(page) {\n    for (let attempt = 0; attempt < 4; attempt++) {\n        const result = await page.evaluate(`\n      (() => {\n        const isVisible = (el) => {\n          if (!(el instanceof HTMLElement)) return false;\n          const style = window.getComputedStyle(el);\n          const rect = el.getBoundingClientRect();\n          return style.display !== 'none'\n            && style.visibility !== 'hidden'\n            && rect.width > 0\n            && rect.height > 0;\n        };\n\n        const dialogs = Array.from(document.querySelectorAll('[role=\"dialog\"]'))\n          .filter((el) => el instanceof HTMLElement && isVisible(el));","sourceCodeStart":297,"sourceCodeEnd":333,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/instagram/post.js#L297-L333","documentation":"If ensureComposerOpen's in-page probe fails for any reason other than auth (result.ok is falsy without reason==='auth'), a generic CommandExecutionError 'Failed to open Instagram post composer' is thrown. Note the probe script returns {ok:true} as a fallback when it cannot find the Create button and no file input exists, so a hard failure typically means page.evaluate itself threw (navigation race, detached context) or result was unexpectedly null.","triggerScenarios":"page.evaluate throwing because the page navigated mid-evaluation or the tab crashed/closed; result being null/undefined due to an interrupted evaluation; Instagram DOM changes that make the probe return a non-ok payload; slow page load leaving the app in a broken intermediate state.","commonSituations":"Flaky network or Instagram slowness during automation runs; the automation browser closed by an external process; concurrent navigation from another step; Instagram A/B UI rollouts altering selectors the probe relies on.","solutions":["Retry the command — composer-open failures are frequently transient; add backoff","Ensure the page is fully loaded and on instagram.com before ensureComposerOpen runs (gotoInstagramHome + waitForSelector on a stable element)","Capture a screenshot/HTML dump on failure to diagnose the actual page state","Update the probe selectors if Instagram changed its DOM; pin a stable layout where possible","Verify the browser session is alive (not crashed/closed) before evaluating"],"exampleFix":"// before\nawait ensureComposerOpen(page); // throws if evaluate races navigation\n// after\nawait page.gotoInstagramHome();\nawait page.waitForSelector('main', { timeout: 30000 });\nfor (let i = 0; i < 3; i++) {\n  try { await ensureComposerOpen(page); break; }\n  catch (e) {\n    if (i === 2 || e instanceof AuthRequiredError) throw e;\n    await page.waitForTimeout(2000);\n  }\n}","handlingStrategy":"retry","validationCode":"// Ensure page readiness before opening the composer\nawait page.goto('https://www.instagram.com/', { waitUntil: 'networkidle' });\nawait page.waitForSelector('main', { timeout: 30000 });\nif (page.isClosed()) throw new Error('Browser page is closed');","typeGuard":"function isComposerOpenFailure(e) {\n  return e instanceof Error\n    && !(e.name === 'AuthRequiredError')\n    && /failed to open instagram post composer/i.test(e.message);\n}","tryCatchPattern":"for (let attempt = 1; attempt <= 3; attempt++) {\n  try { await executeUiInstagramPost(kwargs); break; }\n  catch (e) {\n    if (isAuthRequiredError(e) || attempt === 3) throw e;\n    await new Promise(r => setTimeout(r, 2000 * attempt));\n  }\n}","preventionTips":["Retry with backoff — composer-open failures are often transient (slow load, navigation race)","Wait for a stable page element before running UI automation steps","Never navigate the same tab concurrently while automation is running","Screenshot on failure to capture the real page state for diagnosis","Keep selectors/probes updated when Instagram rolls out UI changes"],"tags":["automation","instagram","transient"],"backgroundTag":"browser-automation-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}