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

  1. Read the reason/detail in the error — they come from the page scraper and pinpoint the missing element
  2. Ensure Trae SOLO is open on the expected main view before running model commands
  3. Retry after the UI finishes loading; add a small delay before invoking
  4. 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

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


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