{"record":{"id":"894e8d2587bffdc2","repo":"jackwener/OpenCLI","slug":"stage1-reason","errorCode":null,"errorMessage":"${stage1.reason}","messagePattern":"\\$\\{stage1\\.reason\\}","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/trae-solo/model.js","lineNumber":74,"sourceCode":"        let opts = [];\n        for (let attempt = 0; attempt < 16; attempt += 1) {\n          await wait(80);\n          opts = Array.from(document.querySelectorAll('.core-model-select-model-item[role=\"option\"]'))\n            .filter((el) => el instanceof HTMLElement && el.offsetParent);\n          if (opts.length) break;\n        }\n        if (!opts.length) {\n          return { ok: false, reason: 'Model menu did not open.' };\n        }\n        const labels = opts.map((o) => {\n          const nameEl = o.querySelector('.core-model-select-model-item-name');\n          return ((nameEl ? nameEl.textContent : o.textContent) || '').trim();\n        });\n        return { ok: true, labels };\n      })()`);\n\n            if (!stage1.ok) {\n                throw new CommandExecutionError(stage1.reason, stage1.detail || '');\n            }\n\n            if (listOnly) {\n                try { await page.evaluate('document.body.click()'); } catch {}\n                return stage1.labels.map((m) => ({ Status: m === current ? 'Active' : 'Available', Model: m }));\n            }\n\n            // Stage 2 (page.click): use real CDP Input.dispatchMouseEvent —\n            // Trae's model menu items don't fire React onSelect from synthetic\n            // pointer events alone. Match by nth-of-type derived from labels.\n            const idx = stage1.labels.findIndex((l) => l.toLowerCase().includes(name));\n            if (idx < 0) {\n                try { await page.evaluate('document.body.click()'); } catch {}\n                throw new CommandExecutionError(\n                    `No model matched: '${name}'`,\n                    'available=' + JSON.stringify(stage1.labels),\n                );\n            }","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/trae-solo/model.js#L56-L92","documentation":"In the model command, stage1 is an in-page evaluate that opens and scrapes the model list, returning {ok:false, reason, detail} on failure. Instead of throwing a generic error, the library surfaces the page-side reason verbatim as a CommandExecutionError, so the message is whatever the browser context reported (e.g. model selector not found).","triggerScenarios":"Calling the model list/switch command when the in-page scraper fails: the model selector UI element isn't present, the page isn't on the expected view, or Trae SOLO's DOM changed so the evaluate returned ok:false.","commonSituations":"Trae SOLO sitting on a different screen than expected (chat panel closed); a Trae SOLO update renamed model-selector DOM nodes; page still loading when the command ran; running list-only against a window where the model dropdown never opens.","solutions":["Read the reason/detail in the error — they come from the page scraper and pinpoint the missing element","Ensure Trae SOLO is open on the expected main view before running model commands","Retry after the UI finishes loading; add a small delay before invoking","If the UI was recently updated, update the library's selectors for the model dropdown"],"exampleFix":"// before\nconst models = await traeSoloCli.model({ list: true }); // throws stage1.reason\n// after\nlet models;\ntry {\n  models = await traeSoloCli.model({ list: true });\n} catch (e) {\n  if (/not found|selector/i.test(e.message + ' ' + (e.detail || ''))) {\n    await new Promise(r => setTimeout(r, 2000));\n    models = await traeSoloCli.model({ list: true });\n  } else throw e;\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  result = await traeSoloCli.model(opts);\n} catch (e) {\n  // message is the page-side stage1.reason; log detail for the DOM cause\n  console.error('Model scrape failed:', e.message, e.detail || '');\n  if (/not found|loading/i.test(e.message)) { /* ensure main view, retry once */ }\n  else throw e;\n}","preventionTips":["Navigate Trae SOLO to the expected main/chat view before model commands","Log e.detail — it carries the page-side failure reason","Retry once after a short delay in case the UI was still loading","After Trae SOLO updates, re-test model listing early to catch selector drift"],"tags":["ui-automation","dom-selector","trae-solo"],"backgroundTag":"dom-selector-mismatch","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}