{"record":{"id":"d3c7daf82cff58ad","repo":"jackwener/OpenCLI","slug":"model-name-cannot-be-empty","errorCode":null,"errorMessage":"model name cannot be empty","messagePattern":"model name cannot be empty","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/codex/model.js","lineNumber":48,"sourceCode":"        .replace(/\\s+/g, ' ')\n        .trim();\n}\n\nconst REASONING_OPTIONS = ['extra high', 'medium', 'high', 'low', 'auto', 'fast', 'speed', 'pro'];\n\nfunction extractReasoning(value) {\n    return REASONING_OPTIONS.find(option => value === option || value.endsWith(` ${option}`)) || '';\n}\n\nfunction extractModelVersion(value) {\n    const match = value.match(/(?:^|\\s)(\\d+(?:\\.\\d+)?)(?=\\s|$)/);\n    return match?.[1] || '';\n}\n\nexport function findUniqueModelOption(labels, rawName) {\n    const name = normalizeModelText(rawName);\n    if (!name) {\n        throw new ArgumentError('model name cannot be empty');\n    }\n    const normalized = labels.map((label) => ({ label, normalized: normalizeModelText(label) }));\n    const exact = normalized.filter(item => item.normalized === name);\n    if (exact.length === 1) {\n        return exact[0].label;\n    }\n    if (exact.length > 1) {\n        throw new CommandExecutionError(`Model name \"${rawName}\" is ambiguous.`, `Matches: ${exact.map(item => item.label).join(', ')}`);\n    }\n    const partial = normalized.filter(item => item.normalized.includes(name));\n    if (partial.length === 1) {\n        return partial[0].label;\n    }\n    if (partial.length > 1) {\n        throw new CommandExecutionError(`Model name \"${rawName}\" is ambiguous.`, `Matches: ${partial.map(item => item.label).join(', ')}`);\n    }\n    return null;\n}","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/codex/model.js#L30-L66","documentation":"`findUniqueModelOption` in clis/codex/model.js normalizes the requested model name and matches it against the model/reasoning labels scraped from the Codex model menu. This ArgumentError is thrown when the normalized name is empty — i.e., no model name was supplied to the `codex model` command while not in list mode. The library treats an empty target as a caller mistake, not a lookup failure.","triggerScenarios":"Calling `opencli codex model` with no positional name and without `--list` in a code path where the empty-name short-circuit (returning the active model) was bypassed — e.g., invoking findUniqueModelOption directly or via `selected` with an empty/whitespace-only rawName.","commonSituations":"Scripting the CLI with a shell variable that is empty (`MODEL=\"\" opencli codex model \"$MODEL\"`); passing only whitespace; a config file with a missing `model:` key; calling the exported helper with null/undefined in tests or integrations.","solutions":["Pass a model or reasoning-level name: `opencli codex model \"gpt-5.5\"` or `opencli codex model high`.","Use `opencli codex model --list` to see available options when you don't know the exact name.","Fix the calling script/config so the variable holding the model name is non-empty before invoking.","If calling the API directly, validate the name is non-empty before calling findUniqueModelOption, or handle ArgumentError."],"exampleFix":"// before\nconst name = process.env.CODEX_MODEL; // may be undefined\nconst selected = findUniqueModelOption(labels, name); // throws ArgumentError\n// after\nconst name = process.env.CODEX_MODEL;\nif (!name || !name.trim()) throw new Error('CODEX_MODEL must be set, e.g. gpt-5.5');\nconst selected = findUniqueModelOption(labels, name);","handlingStrategy":"validation","validationCode":"const name = (kwargs.name || '').trim();\nif (!name) {\n  // read-only mode: fetch current model instead of switching\n  return run('opencli codex model'); // no args returns active model\n}","typeGuard":"function isValidModelName(v) { return typeof v === 'string' && v.trim().length > 0; }","tryCatchPattern":"try {\n  await switchModel(name);\n} catch (err) {\n  if (err instanceof ArgumentError && /cannot be empty/.test(err.message)) {\n    // fall back to reading the active model or prompt for a name\n  } else throw err;\n}","preventionTips":["Always pass a non-empty positional name when switching","Default empty-name invocations to --list or the read path","Validate env/config variables holding model names before invoking","Check shell quoting so $MODEL isn't expanded to empty"],"tags":["argument-error","validation","cli","codex"],"backgroundTag":"missing-required-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}