{"record":{"id":"c372072ef6751a3c","repo":"jackwener/OpenCLI","slug":"could-not-open-the-uploaded-image-action-menu-for","errorCode":null,"errorMessage":"Could not open the uploaded image action menu for Describe","messagePattern":"Could not open the uploaded image action menu for Describe","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/midjourney/describe.js","lineNumber":77,"sourceCode":"          if (prompts.length >= 4) {\n            groups.push(prompts.slice(0, 4));\n            break;\n          }\n        }\n      }\n      return groups;\n    });\n    const menuMarked = await page.evaluate((url) => {\n      const image = [...document.querySelectorAll('img[src]')].find((node) => node.src === url);\n      let card = image;\n      while (card && !String(card.className).includes('group/img')) card = card.parentElement;\n      const button = card?.querySelector('button');\n      if (!button) return false;\n      button.setAttribute('data-opencli-describe-menu', '1');\n      return true;\n    }, sourceUrl);\n    if (!menuMarked) {\n      throw new CommandExecutionError('Could not open the uploaded image action menu for Describe');\n    }\n    await page.click('[data-opencli-describe-menu=\"1\"]');\n    await page.wait(0.4);\n    const startedAt = new Date().toISOString();\n    const clicked = await page.evaluate(() => {\n      const button = [...document.querySelectorAll('button,[role=\"menuitem\"]')]\n        .find((node) => node.textContent?.trim() === 'Describe' && node.getBoundingClientRect().width > 0);\n      if (!button) return false;\n      button.click();\n      return true;\n    });\n    if (!clicked) throw new CommandExecutionError('Midjourney did not expose a Describe action for the uploaded image');\n\n    const deadline = Date.now() + timeout * 1000;\n    let prompts = [];\n    while (Date.now() < deadline) {\n      const groups = await page.evaluate(() => {\n        const visible = (node) => {","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/midjourney/describe.js#L59-L95","documentation":"After uploading the image, describe locates the uploaded image card in the Midjourney DOM, tags its action-menu button with a data attribute, and clicks it. If page.evaluate cannot find/mark the button (menuMarked falsy), a CommandExecutionError is thrown because the Describe flow cannot proceed without opening that menu.","triggerScenarios":"The upload succeeded but the card's action-menu button is missing/renamed in Midjourney's UI, sourceUrl does not match the rendered card, or the page state is stale/slow (card not yet rendered when evaluate runs).","commonSituations":"Midjourney web UI redesign changing button selectors; slow uploads so the card appears after the check; account/locale variations altering the DOM; the image failing to render (moderation, expired upload).","solutions":["Retry the command — transient render/upload lag often resolves it","Increase the wait before the evaluate step (e.g. wait for the card selector instead of a fixed delay)","Update the DOM selector / data-attribute marking logic in describe.js to match the current Midjourney UI","Verify the upload itself succeeded (check uploadReferenceLibrary returned a valid sourceUrl) and that the account can view the uploaded image","Check whether the image was rejected/needs moderation, which suppresses the action menu"],"exampleFix":"// before\nif (!menuMarked) throw new CommandExecutionError('Could not open the uploaded image action menu for Describe');\n// after\nawait page.waitForSelector(`img[src*=\"${sourceUrl}\"]`, { timeout: 10000 }).catch(() => {});\nconst menuMarked = await page.evaluate(...); // retry once on failure\nif (!menuMarked) throw new CommandExecutionError('Could not open the uploaded image action menu for Describe');","handlingStrategy":"retry","validationCode":"// pre-check the uploaded card exists before marking the menu button\nconst cardReady = await page.waitForSelector(`img[src*=\"${sourceUrl}\"]`, { timeout: 10000 }).then(() => true).catch(() => false);\nif (!cardReady) throw new Error('Uploaded image card not rendered; aborting before Describe menu step');","typeGuard":null,"tryCatchPattern":"try {\n  await describe(page, kwargs);\n} catch (err) {\n  if (err instanceof CommandExecutionError && err.message.includes('action menu for Describe')) {\n    await page.wait(1.5); // let the card finish rendering\n    await describe(page, kwargs); // single retry\n  } else throw err;\n}","preventionTips":["Retry once after a short delay — card rendering is often just slow","Wait on an explicit card/image selector instead of fixed waits","Pin/re-check the automation selectors whenever the Midjourney web UI updates","Confirm uploadReferenceLibrary returned a usable sourceUrl before the menu step","Verify the image was accepted (not moderated/removed) by the account"],"tags":["dom-automation","selector-drift","command-execution-error","midjourney"],"backgroundTag":"ui-selector-not-found","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}