{"record":{"id":"a3ee98407e17a336","repo":"jackwener/OpenCLI","slug":"midjourney-composer-did-not-switch-from-video-to-i","errorCode":null,"errorMessage":"Midjourney composer did not switch from video to image mode","messagePattern":"Midjourney composer did not switch from video to image mode","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/midjourney/utils.js","lineNumber":1335,"sourceCode":"    return Boolean((label && visible(label)) || fast);\n  })));\n}\n\nexport async function ensureImageComposer(page) {\n  const composerMode = async () => unwrapEvaluateResult(await page.evaluate(() => {\n    const visible = (button) => Boolean(button && button.getBoundingClientRect().width > 0);\n    if (visible(document.querySelector('button[title=\"Switch to Image\"]'))) return 'video';\n    if (visible(document.querySelector('button[title=\"Switch to Video\"]'))) return 'image';\n    return 'unknown';\n  }));\n  for (let attempt = 0; attempt < 3; attempt += 1) {\n    const mode = await composerMode();\n    if (mode !== 'video') return;\n    await clickVisibleControl(page, 'Switch to Image');\n    await page.wait(0.75);\n  }\n  if (await composerMode() === 'video') {\n    throw new CommandExecutionError('Midjourney composer did not switch from video to image mode');\n  }\n}\n\nexport async function readSiteSettings(page) {\n  const settingsVisible = await isSettingsPanelVisible(page);\n  if (!settingsVisible) {\n    await toggleSettingsPanel(page);\n  }\n  const result = unwrapEvaluateResult(await page.evaluate(() => {\n    const visible = (element) => {\n      const rect = element.getBoundingClientRect();\n      return rect.width > 0 && rect.height > 0 && getComputedStyle(element).display !== 'none';\n    };\n    const exactNode = (text) => [...document.querySelectorAll('h2,a,div,span')]\n      .filter((node) => node.textContent?.trim() === text && visible(node))\n      .sort((left, right) => left.children.length - right.children.length)[0] || null;\n    const isSelected = (button) => button.getAttribute('aria-pressed') === 'true'\n      || button.getAttribute('aria-checked') === 'true'","sourceCodeStart":1317,"sourceCodeEnd":1353,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/midjourney/utils.js#L1317-L1353","documentation":"CommandExecutionError from the ensure-image-mode helper. It reads the composer mode; if it reads 'video' it clicks 'Switch to Image' via clickVisibleControl (which itself needs nativeClick) and waits, then re-checks. If the composer still reports 'video' after the attempt, it throws, meaning the mode switch did not take effect.","triggerScenarios":"Calling the image-mode enforcement routine while the composer is in video mode and either the 'Switch to Image' control is not found/clicked, the native click was swallowed by the UI, or composerMode() keeps returning 'video' due to DOM/DATA attribute changes.","commonSituations":"Slow UI transitions — the 0.75s wait is too short on a slow machine/network; session stuck in video mode; Midjourney renamed the switch control; bridge lacking nativeClick so the click silently did nothing.","solutions":["Ensure the browser bridge supports nativeClick so 'Switch to Image' is actually clicked","Retry the switch with a longer wait after clicking","Check the session/composer is in a state where mode switching is permitted (not mid-generation)","Update the CLI for current 'Switch to Image' control markup"],"exampleFix":"// before\nawait ensureImageMode(page);\n// after\nfor (let i = 0; i < 3; i++) {\n  try { await ensureImageMode(page); return; }\n  catch (e) { await page.wait(2); }\n}\nthrow new Error('Composer stayed in video mode');","handlingStrategy":"retry","validationCode":"// nothing to check pre-call beyond nativeClick support\nif (typeof page.nativeClick !== 'function') throw new Error('nativeClick required for mode switch');","typeGuard":null,"tryCatchPattern":"for (let attempt = 0; attempt < 3; attempt++) {\n  try { await ensureImageMode(page); break; }\n  catch (e) {\n    if (!String(e.message).includes('video to image')) throw e;\n    await page.wait(2);\n  }\n}","preventionTips":["Ensure bridge nativeClick works so the switch click registers","Allow generous waits on slow machines","Avoid invoking mid-generation when mode switching is blocked","Keep the CLI current for 'Switch to Image' markup"],"tags":["browser-automation","ui-state","midjourney"],"backgroundTag":"ui-state-transition-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}