jackwener/OpenCLI · error · CommandExecutionError
Midjourney did not expose a Describe action for the uploaded
Error message
Midjourney did not expose a Describe action for the uploaded image
What it means
This CommandExecutionError is thrown when the browser automation could not find a visible, clickable 'Describe' button or menu item on the Midjourney web UI after uploading an image. The library clicks 'Describe' via page.evaluate by scanning all button/[role=menuitem] nodes for exact text 'Describe' with nonzero width; if none is found, the Describe workflow cannot proceed and this error aborts the command.
Source
Thrown at clis/midjourney/describe.js:89
const button = card?.querySelector('button');
if (!button) return false;
button.setAttribute('data-opencli-describe-menu', '1');
return true;
}, sourceUrl);
if (!menuMarked) {
throw new CommandExecutionError('Could not open the uploaded image action menu for Describe');
}
await page.click('[data-opencli-describe-menu="1"]');
await page.wait(0.4);
const startedAt = new Date().toISOString();
const clicked = await page.evaluate(() => {
const button = [...document.querySelectorAll('button,[role="menuitem"]')]
.find((node) => node.textContent?.trim() === 'Describe' && node.getBoundingClientRect().width > 0);
if (!button) return false;
button.click();
return true;
});
if (!clicked) throw new CommandExecutionError('Midjourney did not expose a Describe action for the uploaded image');
const deadline = Date.now() + timeout * 1000;
let prompts = [];
while (Date.now() < deadline) {
const groups = await page.evaluate(() => {
const visible = (node) => {
const rect = node.getBoundingClientRect();
return rect.width > 0 && rect.height > 0;
};
const found = [];
const markers = [...document.querySelectorAll('div')]
.filter((node) => node.children.length === 0 && node.textContent?.trim() === 'Describe' && visible(node));
for (const marker of markers) {
let root = marker.parentElement;
for (let depth = 0; depth < 16 && root; depth += 1, root = root.parentElement) {
const rows = [...root.querySelectorAll('p')]
.filter(visible)
.map((node) => node.textContent?.trim().replace(/\s+/g, ' ') || '')View on GitHub (pinned to 49907e53dc)
Solutions
- Re-run the command after confirming the image upload completed and the Describe option is visible in the browser session
- Re-authenticate/refresh the Midjourney cookie session and retry, since an expired session can render the UI without actions
- Check whether Midjourney renamed the Describe action after a UI update; update the selector/text match in clis/midjourney/describe.js if needed
- Verify the uploaded file is a supported image type and size, then retry
- Increase the wait before searching for the button so the page/menu finishes rendering
Example fix
// before
const button = [...document.querySelectorAll('button,[role="menuitem"]')]
.find((node) => node.textContent?.trim() === 'Describe' && node.getBoundingClientRect().width > 0);
// after (tolerate partial labels)
const button = [...document.querySelectorAll('button,[role="menuitem"]')]
.find((node) => /describe/i.test(node.textContent || '') && node.getBoundingClientRect().width > 0); Defensive patterns
Strategy: try-catch
Validate before calling
// Verify the Describe action exists before invoking the command
const hasDescribe = await page.evaluate(() =>
[...document.querySelectorAll('button,[role="menuitem"]')].some(
(n) => n.textContent?.trim() === 'Describe' && n.getBoundingClientRect().width > 0,
),
);
if (!hasDescribe) throw new Error('Describe action not visible; check upload/session before running.'); Type guard
function isDescribeAction(node) {
return (
node instanceof HTMLElement &&
node.textContent?.trim() === 'Describe' &&
node.getBoundingClientRect().width > 0
);
} Try / catch
try {
await run('midjourney', 'describe', imagePath);
} catch (err) {
if (err.message.includes('did not expose a Describe action')) {
// re-authenticate, confirm upload rendered, and retry once
} else throw err;
} Prevention
- Confirm the image upload finished and is visible before invoking describe
- Keep the Midjourney cookie/session fresh so the full UI renders
- Watch for Midjourney UI changes that rename or move the Describe action
- Retry after a short delay if the page was still loading when the command ran
When it happens
Trigger: After uploading an image, document.querySelectorAll('button,[role=menuitem]') contains no node whose trimmed textContent is exactly 'Describe' with getBoundingClientRect().width > 0 — e.g. the upload silently failed, the Describe menu did not render, the UI labels changed, or the element is hidden.
Common situations: Midjourney UI redesign renaming or moving the Describe action; the image upload failing or being rejected (wrong file type/size) so no Describe option appears; the page not fully loaded or not logged in; popup/overlay blocking the menu from being visible; running in a headless viewport where the element is collapsed.
Related errors
- Midjourney Imagine composer was not found.
- Could not switch to ${wantModel} model
- Claude composer is not available on the current page.
- Codex sidebar extraction returned an invalid payload.
- Could not resolve a stable Codex conversation identity.
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/f4777cb0d471954d.
Report an issue: GitHub.