{"record":{"id":"73a0391a9b8af5bf","repo":"jackwener/OpenCLI","slug":"midjourney-composer-submit-control-was-not-found","errorCode":null,"errorMessage":"Midjourney composer submit control was not found","messagePattern":"Midjourney composer submit control was not found","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/midjourney/utils.js","lineNumber":1271,"sourceCode":"    };\n    const input = document.querySelector('#desktop_input_bar');\n    const row = input?.parentElement;\n    if (!input || !row) return false;\n    const textSubmit = [...row.querySelectorAll('button')]\n      .find((button) => visible(button) && button.textContent?.trim() === 'Submit');\n    const following = [...row.querySelectorAll('button')].filter((button) => (\n      visible(button)\n      && Boolean(input.compareDocumentPosition(button) & Node.DOCUMENT_POSITION_FOLLOWING)\n    ));\n    // In the compact composer the submit icon is the first button after the\n    // text area and Settings is the second. One unlabeled trailing button is\n    // ambiguous, so fail closed instead of risking a click on Settings.\n    const button = textSubmit || (following.length >= 2 ? following[0] : null);\n    if (!button || button.disabled) return false;\n    button.setAttribute('data-opencli-composer-submit', '1');\n    return true;\n  }));\n  if (!marked) throw new CommandExecutionError('Midjourney composer submit control was not found');\n  await page.click('[data-opencli-composer-submit=\"1\"]');\n}\n\nexport async function toggleSettingsPanel(page) {\n  let target = 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 labeled = [...document.querySelectorAll('button')].find((node) => visible(node) && (\n      node.textContent?.trim().replace(/\\s+/g, ' ') === 'Settings'\n      || node.title === 'Settings'\n      || node.getAttribute('aria-label') === 'Settings'\n    ));\n    if (labeled) {\n      const rect = labeled.getBoundingClientRect();\n      return { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 };\n    }","sourceCodeStart":1253,"sourceCodeEnd":1289,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/midjourney/utils.js#L1253-L1289","documentation":"CommandExecutionError from clickComposerSubmit. The helper evaluates page DOM to mark the composer's submit button with data-opencli-composer-submit; the heuristic (text-based submit button or first of >=2 following buttons) must find an enabled button, otherwise it fails closed rather than risking clicking the wrong control (e.g. Settings).","triggerScenarios":"Calling clickComposerSubmit(page) when the Midjourney web composer is not rendered, is collapsed, the submit button is disabled, or the DOM markup changed so the text/heuristic selectors match nothing.","commonSituations":"Running the click before the page/imagining session has finished loading; Midjourney UI redesign changing button labels/structure; being on a page without an imagine composer (e.g. a video or settings view).","solutions":["Wait for the composer to fully render before calling clickComposerSubmit (page.wait or wait for composer selector)","Verify the submit button is enabled (not disabled) and visible in the browser","Update the CLI to a version matching the current Midjourney DOM","Take a DOM snapshot of the composer area and adjust the [data-opencli-composer-submit] marking logic/labels"],"exampleFix":"// before\nawait clickComposerSubmit(page);\n// after\nawait page.wait(1.5); // let composer hydrate\nif (!(await page.$('[data-opencli-composer-submit]'))) {\n  console.warn('Composer submit not present yet');\n}\nawait clickComposerSubmit(page);","handlingStrategy":"try-catch","validationCode":"await page.waitForSelector('[data-opencli-composer-submit], .composer', { timeout: 10000 }).catch(() => null);","typeGuard":null,"tryCatchPattern":"try {\n  await clickComposerSubmit(page);\n} catch (e) {\n  if (String(e.message).includes('composer submit control')) {\n    await page.wait(2);\n    await clickComposerSubmit(page); // retry after render\n  } else throw e;\n}","preventionTips":["Wait for composer hydration before submitting","Verify submit button is enabled before calling","Keep the CLI updated against Midjourney DOM changes","Fail fast if you are not on the imagine composer page"],"tags":["browser-automation","dom-selector","midjourney"],"backgroundTag":"dom-element-not-found","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}