{"record":{"id":"9a1c0e0b2a931d4d","repo":"jackwener/OpenCLI","slug":"chatgpt-tool-did-not-switch-to-target-label","errorCode":null,"errorMessage":"ChatGPT tool did not switch to ${target.label}.","messagePattern":"ChatGPT tool did not switch to (.+?)\\.","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/chatgpt/utils.js","lineNumber":927,"sourceCode":"                checked,\n                x: Math.round(rect.left + rect.width / 2),\n                y: Math.round(rect.top + rect.height / 2),\n            };\n        })()`)), 'chatgpt tool option click');\n        if (optionCenter.found) break;\n        await page.wait(0.5);\n    }\n    if (!optionCenter?.found) {\n        throw new CommandExecutionError(`Could not find the ChatGPT ${target.label} tool option.`);\n    }\n    if (!optionCenter.checked) {\n        await page.nativeClick(Number(optionCenter.x), Number(optionCenter.y));\n    }\n\n    await page.wait(0.5);\n    const after = await getCurrentChatGPTTool(page);\n    if (after.tool !== target.key) {\n        throw new CommandExecutionError(`ChatGPT tool did not switch to ${target.label}.`);\n    }\n    return { Status: optionCenter.checked ? 'Already selected' : 'Success', Tool: target.label };\n}\n\nexport async function clearChatGPTDraft(page) {\n    await page.evaluate(`\n        (() => {\n            const removeLabels = [/^remove file/i, /^移除文件/];\n            for (let pass = 0; pass < 10; pass += 1) {\n                const button = Array.from(document.querySelectorAll('button')).find((node) => {\n                    const label = node.getAttribute('aria-label') || '';\n                    return removeLabels.some((pattern) => pattern.test(label));\n                });\n                if (!button) break;\n                button.click();\n            }\n\n            const selectors = ${JSON.stringify(COMPOSER_SELECTORS)};","sourceCodeStart":909,"sourceCodeEnd":945,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/chatgpt/utils.js#L909-L945","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Increase the post-click wait before getCurrentChatGPTTool or poll until the state changes","Re-run the command; transient UI lag often makes the second attempt succeed","Verify the click coordinates are correct and no overlay covers the option","Update getCurrentChatGPTTool/option click logic if the ChatGPT UI changed"],"exampleFix":"// before\nawait page.wait(0.5);\nconst after = await getCurrentChatGPTTool(page);\n// after\nlet after = await getCurrentChatGPTTool(page);\nfor (let i = 0; i < 5 && after.tool !== target.key; i++) {\n  await page.wait(1);\n  after = await getCurrentChatGPTTool(page);\n}","handlingStrategy":"retry","validationCode":"const before = await getCurrentChatGPTTool(page);\nif (before.tool === target.key) return; // nothing to do\nif (!before.tool) throw new Error('No active tool detected; UI may not be loaded');","typeGuard":null,"tryCatchPattern":"try {\n  await selectChatGPTTool(page, target);\n} catch (err) {\n  if (err instanceof CommandExecutionError && /did not switch/.test(err.message)) {\n    await sleep(2000);\n    const t = await getCurrentChatGPTTool(page);\n    if (t.tool !== target.key) throw err;\n  } else throw err;\n}","preventionTips":["Allow a longer post-click settle time before asserting the tool state","Re-check state after a short delay instead of asserting immediately","Avoid clicking when overlays or animations are in progress","Log getCurrentChatGPTTool output before and after to diagnose mismatches"],"tags":["automation","chatgpt","ui-state","sync"],"backgroundTag":"ui-state-mismatch","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}