jackwener/OpenCLI · error · CommandExecutionError

${result.reason}

Error message

${result.reason}

What it means

Inside the `codex model` command, the in-page automation script returns `{ ok: false, reason, detail }` for any DOM-level failure (composer missing, trigger button not found, menu not opening, no/ambiguous match). The Node side rethrows that reason as a CommandExecutionError at this line, so this error carries whatever the browser script reported. It is the umbrella failure point for the click-and-select automation inside the Codex UI.

Source

Thrown at clis/codex/model.js:225

      const cinit = {
        bubbles: true, cancelable: true, button: 0, buttons: 1,
        clientX: Math.round(cr.left + cr.width / 2),
        clientY: Math.round(cr.top + cr.height / 2),
      };
      Promise.resolve().then(() => {
        try {
          chosen.dispatchEvent(new PointerEvent('pointerdown', { ...cinit, pointerType: 'mouse' }));
          chosen.dispatchEvent(new MouseEvent('mousedown', cinit));
          chosen.dispatchEvent(new PointerEvent('pointerup', { ...cinit, pointerType: 'mouse' }));
          chosen.dispatchEvent(new MouseEvent('mouseup', cinit));
          chosen.dispatchEvent(new MouseEvent('click', cinit));
        } catch {}
      });
      return { ok: true, switched: true, chosen: chosenLabel, labels };
    })()`));

        if (!result.ok) {
            throw new CommandExecutionError(result.reason, result.detail || '');
        }
        if (listOnly) {
            return result.labels.map((m) => ({ Status: m === current ? 'Active' : 'Available', Model: m }));
        }
        const selected = findUniqueModelOption(result.labels || [], name);
        if (!selected) {
            throw new CommandExecutionError('No model matched.', `wanted=${name} available=${JSON.stringify(result.labels || [])}`);
        }
        if (selected !== result.chosen) {
            throw new CommandExecutionError('Codex model selection was inconsistent.', `expected=${selected} chosen=${result.chosen}`);
        }
        let verified = '';
        for (let attempt = 0; attempt < 20; attempt += 1) {
            await page.wait(0.25);
            const reread = unwrapEvaluateResult(await page.evaluate(`(function() {
        const re = new RegExp(${patternJson});
        const composers = Array.from(document.querySelectorAll('[contenteditable="true"]')).filter((el) => el.offsetParent);
        const last = composers[composers.length - 1];

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Open a chat in Codex so the composer and model button are visible, then retry.
  2. Run `opencli codex model --list` to test whether the menu can be opened at all; if it fails, the DOM drifted — update opencli.
  3. Retry once; slow renders sometimes exceed the menu-open wait window.
  4. Read the error's reason/detail (e.g. 'Model menu did not open after click.') to target the specific failing step.

Example fix

// before
opencli codex model "gpt-5.5"   // fails: 'model trigger button not found in composer'
// after
# open a chat first so the composer exists
opencli codex model --list       # verify menu opens / DOM matches
opencli codex model "gpt-5.5"
Defensive patterns

Strategy: retry

Validate before calling

// ensure a chat/composer exists before switching
const current = await run('opencli codex model'); // throws selectorError if no composer
if (!current) await openNewChat();

Type guard

function automationResultOk(r) { return r && typeof r === 'object' && r.ok === true; }

Try / catch

try {
  await switchModel(name);
} catch (err) {
  if (err instanceof CommandExecutionError) {
    // reason in err.message/detail; wait for UI and retry once
    await sleep(2000);
    return switchModel(name);
  }
  throw err;
}

Prevention

When it happens

Trigger: Running `opencli codex model <name>` when the evaluate script sets ok:false: composer contenteditable not found, model trigger button not matched by MODEL_BTN_TEXT_RE, menu items didn't appear within ~1.3s of the synthetic click, or zero/ambiguous normalized label matches inside the page script.

Common situations: No chat open in Codex so no composer exists; a Codex update changed the composer toolbar DOM so the regex no longer matches; slow UI where the menu takes longer than the 16×80ms wait; synthetic clicks ignored by an updated menu component.

Related errors


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