{"record":{"id":"306355ed33de85bc","repo":"jackwener/OpenCLI","slug":"no-model-matched","errorCode":null,"errorMessage":"No model matched.","messagePattern":"No model matched\\.","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/codex/model.js","lineNumber":232,"sourceCode":"          chosen.dispatchEvent(new PointerEvent('pointerdown', { ...cinit, pointerType: 'mouse' }));\n          chosen.dispatchEvent(new MouseEvent('mousedown', cinit));\n          chosen.dispatchEvent(new PointerEvent('pointerup', { ...cinit, pointerType: 'mouse' }));\n          chosen.dispatchEvent(new MouseEvent('mouseup', cinit));\n          chosen.dispatchEvent(new MouseEvent('click', cinit));\n        } catch {}\n      });\n      return { ok: true, switched: true, chosen: chosenLabel, labels };\n    })()`));\n\n        if (!result.ok) {\n            throw new CommandExecutionError(result.reason, result.detail || '');\n        }\n        if (listOnly) {\n            return result.labels.map((m) => ({ Status: m === current ? 'Active' : 'Available', Model: m }));\n        }\n        const selected = findUniqueModelOption(result.labels || [], name);\n        if (!selected) {\n            throw new CommandExecutionError('No model matched.', `wanted=${name} available=${JSON.stringify(result.labels || [])}`);\n        }\n        if (selected !== result.chosen) {\n            throw new CommandExecutionError('Codex model selection was inconsistent.', `expected=${selected} chosen=${result.chosen}`);\n        }\n        let verified = '';\n        for (let attempt = 0; attempt < 20; attempt += 1) {\n            await page.wait(0.25);\n            const reread = unwrapEvaluateResult(await page.evaluate(`(function() {\n        const re = new RegExp(${patternJson});\n        const composers = Array.from(document.querySelectorAll('[contenteditable=\"true\"]')).filter((el) => el.offsetParent);\n        const last = composers[composers.length - 1];\n        if (!last) return '';\n        let root = last;\n        for (let i = 0; i < 5; i++) root = root.parentElement || root;\n        const btns = Array.from(root.querySelectorAll('button')).filter((b) => b.offsetParent);\n        const match = btns.find((b) => re.test((b.textContent || '').trim()));\n        return match ? (match.textContent || '').trim() : '';\n      })()`));","sourceCodeStart":214,"sourceCodeEnd":250,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/codex/model.js#L214-L250","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Run `opencli codex model --list` and use an exact label from the output.","Check the error detail (wanted=... available=...) and correct the spelling/format of the requested name.","Update Codex or opencli if the model you want genuinely isn't listed.","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)."],"exampleFix":"// before\nopencli codex model \"gpt-5.6\"   // not in menu\n// after\nopencli codex model --list\nopencli codex model \"gpt-5.5\"   # pick a listed label","handlingStrategy":"validation","validationCode":"const listed = await run('opencli codex model --list');\nconst labels = parseLabels(listed);\nconst norm = s => s.toLowerCase().replace(/\\bgpt[-\\s]*/g,'').replace(/\\s+/g,' ').trim();\nif (!labels.some(l => norm(l).includes(norm(wanted)))) {\n  throw new Error(`\"${wanted}\" not offered; available: ${labels.join(', ')}`);\n}","typeGuard":"function labelExists(labels, name) {\n  const n = s => s.toLowerCase().replace(/\\bgpt[-\\s]*/g,'').replace(/\\s+/g,' ').trim();\n  return labels.some(l => n(l) === n(name) || n(l).includes(n(name)));\n}","tryCatchPattern":"try {\n  await switchModel(name);\n} catch (err) {\n  if (err instanceof CommandExecutionError && err.detail?.startsWith('wanted=')) {\n    // parse available= JSON from detail, surface valid options to the user\n  } else throw err;\n}","preventionTips":["Resolve names against `codex model --list` before switching","Keep model names in config in sync with what your Codex build offers","Check the wanted=/available= detail to correct typos","Update Codex/opencli when requesting newly released models"],"tags":["no-match","cli","codex","model-selection"],"backgroundTag":"no-matching-option","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}