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
- Open a chat in Codex so the composer and model button are visible, then retry.
- Run `opencli codex model --list` to test whether the menu can be opened at all; if it fails, the DOM drifted — update opencli.
- Retry once; slow renders sometimes exceed the menu-open wait window.
- 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
- Open a chat in Codex so the composer is present before switching
- Retry once on menu-open timeouts; slow renders can exceed the wait window
- Keep opencli updated when Codex changes composer/menu DOM
- Use --list as a cheap health check of the automation path
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
- Codex extract-diff returned an invalid payload.
- Model name "${rawName}" is ambiguous.
- Codex model selection was inconsistent.
- Codex model switch to "${selected}" was not verified.
- Cannot switch to ${wantModel} model inside an existing conve
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/7e6344901f30ad65.
Report an issue: GitHub.