jackwener/OpenCLI · error · CommandExecutionError

ChatGPT tool did not switch to ${target.label}.

Error message

ChatGPT tool did not switch to ${target.label}.

What it means

After clicking the tool option, selectChatGPTTool re-reads the current tool via getCurrentChatGPTTool and throws this CommandExecutionError if the active tool still does not match target.key — i.e. the click did not take effect or the state check disagrees.

Source

Thrown at clis/chatgpt/utils.js:927

                checked,
                x: Math.round(rect.left + rect.width / 2),
                y: Math.round(rect.top + rect.height / 2),
            };
        })()`)), 'chatgpt tool option click');
        if (optionCenter.found) break;
        await page.wait(0.5);
    }
    if (!optionCenter?.found) {
        throw new CommandExecutionError(`Could not find the ChatGPT ${target.label} tool option.`);
    }
    if (!optionCenter.checked) {
        await page.nativeClick(Number(optionCenter.x), Number(optionCenter.y));
    }

    await page.wait(0.5);
    const after = await getCurrentChatGPTTool(page);
    if (after.tool !== target.key) {
        throw new CommandExecutionError(`ChatGPT tool did not switch to ${target.label}.`);
    }
    return { Status: optionCenter.checked ? 'Already selected' : 'Success', Tool: target.label };
}

export async function clearChatGPTDraft(page) {
    await page.evaluate(`
        (() => {
            const removeLabels = [/^remove file/i, /^移除文件/];
            for (let pass = 0; pass < 10; pass += 1) {
                const button = Array.from(document.querySelectorAll('button')).find((node) => {
                    const label = node.getAttribute('aria-label') || '';
                    return removeLabels.some((pattern) => pattern.test(label));
                });
                if (!button) break;
                button.click();
            }

            const selectors = ${JSON.stringify(COMPOSER_SELECTORS)};

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Increase the post-click wait before getCurrentChatGPTTool or poll until the state changes
  2. Re-run the command; transient UI lag often makes the second attempt succeed
  3. Verify the click coordinates are correct and no overlay covers the option
  4. Update getCurrentChatGPTTool/option click logic if the ChatGPT UI changed

Example fix

// before
await page.wait(0.5);
const after = await getCurrentChatGPTTool(page);
// after
let after = await getCurrentChatGPTTool(page);
for (let i = 0; i < 5 && after.tool !== target.key; i++) {
  await page.wait(1);
  after = await getCurrentChatGPTTool(page);
}
Defensive patterns

Strategy: retry

Validate before calling

const before = await getCurrentChatGPTTool(page);
if (before.tool === target.key) return; // nothing to do
if (!before.tool) throw new Error('No active tool detected; UI may not be loaded');

Try / catch

try {
  await selectChatGPTTool(page, target);
} catch (err) {
  if (err instanceof CommandExecutionError && /did not switch/.test(err.message)) {
    await sleep(2000);
    const t = await getCurrentChatGPTTool(page);
    if (t.tool !== target.key) throw err;
  } else throw err;
}

Prevention

When it happens

Trigger: The nativeClick hit the wrong coordinates (layout shifted between locate and click), the option was toggled off instead of on, ChatGPT rejected/delayed the tool switch, or getCurrentChatGPTTool reads a stale/different DOM node than the one clicked.

Common situations: Slow ChatGPT UI where the 0.5s post-click wait is insufficient for state to update; overlapping UI overlays stealing the click; the tool requires confirmation the automation does not perform.

Related errors


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