jackwener/OpenCLI · error · CommandExecutionError
${stage1.reason}
Error message
${stage1.reason} What it means
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).
Source
Thrown at clis/trae-solo/model.js:74
let opts = [];
for (let attempt = 0; attempt < 16; attempt += 1) {
await wait(80);
opts = Array.from(document.querySelectorAll('.core-model-select-model-item[role="option"]'))
.filter((el) => el instanceof HTMLElement && el.offsetParent);
if (opts.length) break;
}
if (!opts.length) {
return { ok: false, reason: 'Model menu did not open.' };
}
const labels = opts.map((o) => {
const nameEl = o.querySelector('.core-model-select-model-item-name');
return ((nameEl ? nameEl.textContent : o.textContent) || '').trim();
});
return { ok: true, labels };
})()`);
if (!stage1.ok) {
throw new CommandExecutionError(stage1.reason, stage1.detail || '');
}
if (listOnly) {
try { await page.evaluate('document.body.click()'); } catch {}
return stage1.labels.map((m) => ({ Status: m === current ? 'Active' : 'Available', Model: m }));
}
// Stage 2 (page.click): use real CDP Input.dispatchMouseEvent —
// Trae's model menu items don't fire React onSelect from synthetic
// pointer events alone. Match by nth-of-type derived from labels.
const idx = stage1.labels.findIndex((l) => l.toLowerCase().includes(name));
if (idx < 0) {
try { await page.evaluate('document.body.click()'); } catch {}
throw new CommandExecutionError(
`No model matched: '${name}'`,
'available=' + JSON.stringify(stage1.labels),
);
}View on GitHub (pinned to 49907e53dc)
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
Example fix
// before
const models = await traeSoloCli.model({ list: true }); // throws stage1.reason
// after
let models;
try {
models = await traeSoloCli.model({ list: true });
} catch (e) {
if (/not found|selector/i.test(e.message + ' ' + (e.detail || ''))) {
await new Promise(r => setTimeout(r, 2000));
models = await traeSoloCli.model({ list: true });
} else throw e;
} Defensive patterns
Strategy: try-catch
Try / catch
try {
result = await traeSoloCli.model(opts);
} catch (e) {
// message is the page-side stage1.reason; log detail for the DOM cause
console.error('Model scrape failed:', e.message, e.detail || '');
if (/not found|loading/i.test(e.message)) { /* ensure main view, retry once */ }
else throw e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Mode toggle did not reach requested state "${want}".
- 找不到消息输入框
- Could not find an add-to-cart button on the product page.
- Instagram action button not found: ${labels.join(' / ')}
- sidebar-toggle failed
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/894e8d2587bffdc2.
Report an issue: GitHub.