jackwener/OpenCLI · error · CommandExecutionError

No model matched.

Error message

No model matched.

What it means

After the page script clicks the menu item, the Node side independently re-resolves the requested name against the scraped labels via `findUniqueModelOption`. This CommandExecutionError is thrown when that re-resolution finds no label (exact or substring) matching the requested name, meaning the wanted model/reasoning option was not present among the menu items actually scraped.

Source

Thrown at clis/codex/model.js:232

          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];
        if (!last) return '';
        let root = last;
        for (let i = 0; i < 5; i++) root = root.parentElement || root;
        const btns = Array.from(root.querySelectorAll('button')).filter((b) => b.offsetParent);
        const match = btns.find((b) => re.test((b.textContent || '').trim()));
        return match ? (match.textContent || '').trim() : '';
      })()`));

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Run `opencli codex model --list` and use an exact label from the output.
  2. Check the error detail (wanted=... available=...) and correct the spelling/format of the requested name.
  3. Update Codex or opencli if the model you want genuinely isn't listed.
  4. If the label is visible in the UI but missing from --list, report/patch the label-filtering logic (new unfiltered chat-action entries or kbd-removal drift).

Example fix

// before
opencli codex model "gpt-5.6"   // not in menu
// after
opencli codex model --list
opencli codex model "gpt-5.5"   # pick a listed label
Defensive patterns

Strategy: validation

Validate before calling

const listed = await run('opencli codex model --list');
const labels = parseLabels(listed);
const norm = s => s.toLowerCase().replace(/\bgpt[-\s]*/g,'').replace(/\s+/g,' ').trim();
if (!labels.some(l => norm(l).includes(norm(wanted)))) {
  throw new Error(`"${wanted}" not offered; available: ${labels.join(', ')}`);
}

Type guard

function labelExists(labels, name) {
  const n = s => s.toLowerCase().replace(/\bgpt[-\s]*/g,'').replace(/\s+/g,' ').trim();
  return labels.some(l => n(l) === n(name) || n(l).includes(n(name)));
}

Try / catch

try {
  await switchModel(name);
} catch (err) {
  if (err instanceof CommandExecutionError && err.detail?.startsWith('wanted=')) {
    // parse available= JSON from detail, surface valid options to the user
  } else throw err;
}

Prevention

When it happens

Trigger: Running `opencli codex model <name>` with a name that doesn't correspond to any visible menu item — typo'd model names, requesting a model not offered on the account, or the page script's label filtering (kbd removal, chat-action exclusion) dropping the relevant item.

Common situations: Typo or wrong naming convention ('gpt55' vs 'GPT-5.5'); requesting a newer model than the Codex build offers; account tier lacking the model; Codex renaming menu labels after an update.

Related errors


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