{"record":{"id":"591f79b966841626","repo":"jackwener/OpenCLI","slug":"pubmed-label-must-be-one-of-choices-join","errorCode":null,"errorMessage":"pubmed ${label} must be one of: ${choices.join(', ')}","messagePattern":"pubmed (.+?) must be one of: (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/pubmed/utils.js","lineNumber":56,"sourceCode":"    }\n    return n;\n}\n\nexport function requireYear(value, label) {\n    if (value === undefined || value === null || value === '') {\n        return undefined;\n    }\n    const year = requireBoundedInt(value, 1900, 3000, label);\n    if (year < 1800) {\n        throw new ArgumentError(`pubmed ${label} must be >= 1800`);\n    }\n    return year;\n}\n\nexport function requireChoice(value, choices, label, defaultValue) {\n    const text = String(value ?? defaultValue).trim();\n    if (!choices.includes(text)) {\n        throw new ArgumentError(`pubmed ${label} must be one of: ${choices.join(', ')}`);\n    }\n    return text;\n}\n\nexport function buildEutilsUrl(tool, params = {}) {\n    const searchParams = new URLSearchParams();\n    searchParams.set('db', 'pubmed');\n    if (!params.retmode) {\n        searchParams.set('retmode', 'json');\n    }\n    if (process.env.NCBI_API_KEY) {\n        searchParams.set('api_key', process.env.NCBI_API_KEY);\n    }\n    if (process.env.NCBI_EMAIL) {\n        searchParams.set('email', process.env.NCBI_EMAIL);\n    }\n    for (const [key, value] of Object.entries(params)) {\n        if (value !== undefined && value !== null && value !== '') {","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/pubmed/utils.js#L38-L74","documentation":"requireChoice validates enum-like options (position, sort, direction) against an allowed list, after applying the default. Values outside the list throw ArgumentError 'pubmed <label> must be one of: <choice1, choice2, ...>'.","triggerScenarios":"`--sort newest` when only 'relevance'/'pub_date' style values are accepted, `--direction ascending` instead of 'asc', misspelled position values.","commonSituations":"Guessing option names without reading --help, copying flags from a different CLI, case mismatches ('ASC' vs 'asc').","solutions":["Use exactly one of the values listed in the error message (they are comma-joined)","Run the command with --help to see documented choices","Match the exact casing of the allowed values"],"exampleFix":"// before\n--direction ascending\n// after\n--direction asc   // or whichever value the error lists","handlingStrategy":"validation","validationCode":"const ALLOWED_SORT = ['relevance', 'pub_date']; // see --help\nif (!ALLOWED_SORT.includes(sort)) {\n  throw new Error(`sort must be one of: ${ALLOWED_SORT.join(', ')}`);\n}","typeGuard":"function isOneOf(v, choices) {\n  return choices.includes(String(v ?? '').trim());\n}","tryCatchPattern":"try {\n  await pubmedSearch(query, { sort });\n} catch (err) {\n  const m = /must be one of: (.+)/.exec(err.message ?? '');\n  if (err instanceof ArgumentError && m) {\n    console.error(`Invalid sort '${sort}'. Allowed: ${m[1]}`);\n    process.exitCode = 2;\n  } else { throw err; }\n}","preventionTips":["Use exactly the values listed in --help or the error message","Watch for case sensitivity and abbreviations (asc vs ascending)","Do not copy enum flags between different CLIs without checking"],"tags":["validation","argument-error","enum-values","cli-options"],"backgroundTag":"invalid-enumeration-value","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}