jackwener/OpenCLI · error · CommandExecutionError

Could not find the ChatGPT tools menu button in the composer

Error message

Could not find the ChatGPT tools menu button in the composer.

What it means

selectChatGPTTool evaluates a script to find the tools-menu button in the composer; if no element matches, menuButton.found is false and it throws CommandExecutionError. Like the model-selector case, this exists to avoid clicking invalid coordinates when the expected control is missing from the DOM.

Source

Thrown at clis/chatgpt/utils.js:854

        const isVisible = (el) => {
            if (!(el instanceof HTMLElement)) return false;
            const style = window.getComputedStyle(el);
            if (style.display === 'none' || style.visibility === 'hidden') return false;
            const rect = el.getBoundingClientRect();
            return rect.width > 0 && rect.height > 0;
        };
        const button = document.querySelector('button[data-testid="composer-plus-btn"]');
        if (!(button instanceof HTMLElement) || !isVisible(button)) return { found: false };
        button.scrollIntoView({ block: 'center', inline: 'center' });
        const rect = button.getBoundingClientRect();
        return {
            found: true,
            x: Math.round(rect.left + rect.width / 2),
            y: Math.round(rect.top + rect.height / 2),
        };
    })()`)), 'chatgpt tools menu button');
    if (!menuButton.found) {
        throw new CommandExecutionError('Could not find the ChatGPT tools menu button in the composer.');
    }
    await page.nativeClick(Number(menuButton.x), Number(menuButton.y));
    await page.wait(0.5);

    let optionCenter = null;
    for (let attempt = 0; attempt < 10; attempt += 1) {
        optionCenter = requireObjectEvaluateResult(unwrapEvaluateResult(await page.evaluate(`(() => {
            const isVisible = (el) => {
                if (!(el instanceof HTMLElement)) return false;
                const style = window.getComputedStyle(el);
                if (style.display === 'none' || style.visibility === 'hidden') return false;
                const rect = el.getBoundingClientRect();
                return rect.width > 0 && rect.height > 0;
            };
            const normalize = (value) => String(value || '').replace(/\\s+/g, ' ').trim();
            const compact = (value) => normalize(value).toLowerCase().replace(/[^\\p{L}\\p{N}]+/gu, '');
            const labels = ${JSON.stringify(target.labels)};
            const optionSelector = '[role="menuitemradio"], [role="menuitem"], [role="option"], button, div[tabindex="0"]';

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry after a brief wait so the composer toolbar finishes rendering.
  2. Open ChatGPT manually and confirm the tools ("+") button exists in your UI variant/locale; exit special modes like canvas/voice.
  3. Set OPENCLI_CHATGPT_MODEL_DEBUG=1 to trace the failing step.
  4. Update the opencli package so its selectors match the current ChatGPT DOM.

Example fix

// before
await selectChatGPTTool(page, 'deep-research'); // tools button not yet rendered
// after
await page.wait(2);
await selectChatGPTTool(page, 'deep-research');
Defensive patterns

Strategy: retry

Validate before calling

await ensureChatGPTComposer(page);
await page.wait(1.5); // let composer toolbar (with the "+" tools button) render

Type guard

function toolsButtonFound(res) {
  return res != null && res.found === true && Number.isFinite(Number(res.x)) && Number.isFinite(Number(res.y));
}

Try / catch

for (let i = 0; i < 3; i++) {
  try { return await selectChatGPTTool(page, tool); }
  catch (err) {
    if (!(err instanceof CommandExecutionError) || !/tools menu button/.test(err.message)) throw err;
    await page.wait(1.5);
  }
}
throw new Error('tools menu button never appeared');

Prevention

When it happens

Trigger: The tools menu button ("+" actions button) is not present in the composer — ChatGPT UI variant/redesign, page not hydrated yet, locale/labels mismatch, special composer states (canvas, voice mode, some workspaces) hiding the tools button, or the evaluate script being blocked/returning unexpected shapes.

Common situations: New ChatGPT layouts that relocate or rename the tools button; automation running before the composer toolbar renders; UI language not covered by the labels list; temporary chat or feature-flagged variants where the tools menu is absent.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/3d10cfb0c4499d99. Report an issue: GitHub.