{"record":{"id":"83dc2f1209895890","repo":"jackwener/OpenCLI","slug":"settings-button-not-found","errorCode":null,"errorMessage":"Settings button not found","messagePattern":"Settings button not found","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/qoder/ui.js","lineNumber":129,"sourceCode":"});\n\n// -------- settings --------\ncli({\n    site: 'qoder',\n    name: 'settings',\n    access: 'write',\n    description: 'Click the Settings button in the Qoder sidebar.',\n    domain: 'localhost',\n    strategy: Strategy.UI,\n    browser: true,\n    args: [],\n    columns: ['Status'],\n    func: async (page) => {\n        const res = await evaluateQoder(page, clickByTextScript(['Settings']));\n        if (!res?.ok) {\n            // Fallback: try aria-label.\n            const ariaRes = await evaluateQoder(page, clickFirstScript(['button[aria-label=\"Settings\"]']));\n            if (!ariaRes?.ok) throw new CommandExecutionError('Settings button not found', '');\n        }\n        await page.wait(0.5);\n        return [{ Status: 'clicked' }];\n    },\n});\n\n// -------- knowledge --------\ncli({\n    site: 'qoder',\n    name: 'knowledge',\n    access: 'write',\n    description: 'Open the Knowledge view (Qoder\\'s personal/team knowledge base).',\n    domain: 'localhost',\n    strategy: Strategy.UI,\n    browser: true,\n    args: [],\n    columns: ['Status'],\n    func: async (page) => {","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/qoder/ui.js#L111-L147","documentation":"Thrown by the qoder settings UI command when neither clicking visible text 'Settings' nor the aria-label fallback button[aria-label=\"Settings\"] succeeds. The command raises CommandExecutionError('Settings button not found') because the settings panel can't be opened. Both the text-based and attribute-based selectors missed the real button.","triggerScenarios":"The settings entry is an icon-only gear button with a different aria-label; the button lives inside a menu that must be opened first; the settings text is localized; the button is hidden until hover; Qoder update changed the label.","commonSituations":"Localized UI (e.g. 设置 instead of Settings); settings behind a user/avatar dropdown; headless mode where hover-revealed controls stay hidden; page not fully loaded.","solutions":["Inspect the live DOM for the settings control and update both the text array and the aria-label selector.","Add common localized variants (e.g. '设置') and attribute selectors like [data-testid=\"settings\"], button[title=\"Settings\"].","Open any parent menu/avatar dropdown before clicking Settings.","Wait for the page to fully load, and check the control isn't hover-gated in headless."],"exampleFix":"// before\nconst ariaRes = await evaluateQoder(page, clickFirstScript(['button[aria-label=\"Settings\"]']));\n// after\nconst ariaRes = await evaluateQoder(page, clickFirstScript(['button[aria-label=\"Settings\"]', 'button[title=\"Settings\"]', '[data-testid=\"settings-button\"]', 'button[aria-label=\"设置\"]']));","handlingStrategy":"fallback","validationCode":"const settingsBtn = await page.evaluate(`Array.from(document.querySelectorAll('button')).some(b => /settings/i.test(b.textContent || '') || b.getAttribute('aria-label') === 'Settings')`);\nif (!settingsBtn) console.warn('Settings control not visible; it may live behind a menu');","typeGuard":"function isClickOk(res) { return Boolean(res && res.ok === true); }","tryCatchPattern":"try {\n  await openSettings(page);\n} catch (e) {\n  if (/Settings button not found/.test(String(e.message))) console.warn('Open the avatar/user menu first, then retry');\n  else throw e;\n}","preventionTips":["Check whether Settings is nested inside a dropdown and open the parent first.","Include localized labels (e.g. '设置') in text matching.","Use data-testid/aria-label fallbacks alongside text.","Account for hover-revealed controls in headless mode."],"tags":["ui-automation","dom-selector","click-failed"],"backgroundTag":"selector-not-found","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}