{"record":{"id":"c334576ca5c8e0fa","repo":"jackwener/OpenCLI","slug":"semanticscholar-label-cannot-be-empty","errorCode":null,"errorMessage":"semanticscholar ${label} cannot be empty","messagePattern":"semanticscholar (.+?) cannot be empty","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/semanticscholar/utils.js","lineNumber":29,"sourceCode":"\nexport const S2_GRAPH_BASE = 'https://api.semanticscholar.org/graph/v1';\nexport const S2_REC_BASE = 'https://api.semanticscholar.org/recommendations/v1';\nconst UA = 'opencli-semanticscholar-adapter (+https://github.com/jackwener/opencli)';\n\n// Semantic Scholar paperId: 40-char lowercase hex (SHA-ish).\nconst S2_PAPER_ID = /^[0-9a-f]{40}$/i;\n// DOIs: anything starting with 10. after an optional `doi:` / `doi.org/` prefix.\nconst DOI_BARE = /^10\\.\\S+$/;\n// arXiv ids: modern `YYMM.NNNNN` form or legacy `archive/YYMMNNN`.\nconst ARXIV_MODERN = /^\\d{4}\\.\\d{4,5}(?:v\\d+)?$/;\nconst ARXIV_LEGACY = /^[a-z-]+\\/\\d{7}(?:v\\d+)?$/i;\n// Other Semantic Scholar accepted prefixes that we pass through verbatim.\nconst PREFIXED = /^(ARXIV|MAG|ACL|PMID|PMCID|URL|CorpusId|DBLP):/i;\n\nexport function requireString(value, label) {\n    const s = String(value ?? '').trim();\n    if (!s) {\n        throw new ArgumentError(`semanticscholar ${label} cannot be empty`);\n    }\n    return s;\n}\n\nexport function requireBoundedInt(value, defaultValue, maxValue, label = 'limit') {\n    const raw = value ?? defaultValue;\n    const n = typeof raw === 'number' ? raw : Number(raw);\n    if (!Number.isInteger(n) || n <= 0) {\n        throw new ArgumentError(`semanticscholar ${label} must be a positive integer`);\n    }\n    if (n > maxValue) {\n        throw new ArgumentError(`semanticscholar ${label} must be <= ${maxValue}`);\n    }\n    return n;\n}\n\n/**\n * Resolve a user-supplied paper reference to a Semantic Scholar paper id","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/semanticscholar/utils.js#L11-L47","documentation":"requireString validates that a user-supplied string argument (label identifies which, e.g. 'query') is non-empty after trimming; it throws ArgumentError when the value is null, undefined, or whitespace. The library throws this early so an empty required parameter never reaches the API as a malformed request.","triggerScenarios":"Calling a semanticscholar command without its required string argument, e.g. `opencli semanticscholar search` with no query, or passing an empty/whitespace-only string ('', '   '), or a variable that is undefined/null.","commonSituations":"Shell scripts where an interpolated variable is empty ($QUERY unset); copy-paste dropping the argument; CI pipelines with missing env vars feeding the CLI.","solutions":["Re-run the command and supply the required argument (e.g. the search query).","In scripts, default or assert the variable before invoking: `[ -n \"$QUERY\" ] || { echo 'QUERY is empty'; exit 1; }`.","If the value should be optional, pass a sensible non-empty default instead of an empty string."],"exampleFix":"// before\nconst query = requireString(args.query, 'query'); // throws when args.query is ''\n// after\nguard: if (!args.query?.trim()) { print usage; exit; }\nconst query = requireString(args.query, 'query');","handlingStrategy":"validation","validationCode":"const query = (process.argv[3] ?? '').trim();\nif (!query) { console.error('usage: opencli semanticscholar search <query>'); process.exit(1); }","typeGuard":"function isNonEmptyString(v) { return typeof v === 'string' && v.trim().length > 0; }","tryCatchPattern":"try {\n    await runSearch(args);\n} catch (err) {\n    if (err instanceof ArgumentError && /cannot be empty/.test(err.message)) {\n        console.error(`Missing argument: ${err.message}. See --help.`);\n        process.exit(2);\n    }\n    throw err;\n}","preventionTips":["Use ${VAR:?msg} shell expansions so unset variables fail before the CLI runs.","Quote arguments to avoid word-splitting producing empty tokens.","Check --help output for required positional arguments.","In CI, assert required env/inputs exist before invoking the CLI."],"tags":["argument-validation","cli","input"],"backgroundTag":"missing-required-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}