{"record":{"id":"97260a62cfbb831e","repo":"jackwener/OpenCLI","slug":"openreview-label-is-required","errorCode":null,"errorMessage":"openreview ${label} is required","messagePattern":"openreview (.+?) is required","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/openreview/utils.js","lineNumber":50,"sourceCode":"    if (n > maxValue) {\n        throw new ArgumentError(`openreview ${label} must be <= ${maxValue}`);\n    }\n    return n;\n}\n\nexport function requireNonNegativeInt(value, defaultValue, label = 'offset') {\n    const raw = value ?? defaultValue;\n    const n = coerceInt(raw);\n    if (!Number.isInteger(n) || n < 0) {\n        throw new ArgumentError(`openreview ${label} must be a non-negative integer`);\n    }\n    return n;\n}\n\nexport function requireForumId(value, label = 'id') {\n    const id = String(value ?? '').trim();\n    if (!id) {\n        throw new ArgumentError(`openreview ${label} is required`);\n    }\n    if (!ID_PATTERN.test(id)) {\n        throw new ArgumentError(`openreview ${label} \"${value}\" is not a valid forum id (expected 6-20 chars of [A-Za-z0-9_-])`);\n    }\n    return id;\n}\n\n/** OpenReview profile ids are `~...N` slugs and may include dots, hyphens, and Unicode letters. */\nconst PROFILE_ID_PATTERN = /^~(?=.*\\p{L})[\\p{L}\\p{M}0-9._-]+\\d+$/u;\n\nexport function requireProfileId(value, label = 'profile') {\n    const id = String(value ?? '').trim();\n    if (!id) {\n        throw new ArgumentError(`openreview ${label} is required`);\n    }\n    if (!PROFILE_ID_PATTERN.test(id)) {\n        throw new ArgumentError(`openreview ${label} \"${value}\" is not a valid profile id (expected \"~First_Last1\" or similar; find it on the author's openreview.net profile URL)`);\n    }","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/openreview/utils.js#L32-L68","documentation":"requireForumId validates OpenReview forum/submission ids before any API call. It throws ArgumentError when the value is missing or whitespace-only, because an empty id would produce a meaningless API request. The label parameter names the argument in the message (e.g. 'id' or 'forum').","triggerScenarios":"Calling id(args) or forum(args) with args.id/args.forum undefined, null, empty string, or a string of only whitespace.","commonSituations":"User forgot the positional argument on the CLI; a script passes an empty variable after trimming; a JSON config has \"forum\": \"\"; shell variable unset so $FORUM expands to nothing.","solutions":["Pass a non-empty forum id (e.g. the submission id from the OpenReview URL, like 'AbCdEf123456').","Check CLI help for the required argument name and re-run with it supplied.","In scripts, default/guard the variable: [ -n \"$FORUM\" ] || { echo 'FORUM required'; exit 1; }."],"exampleFix":"// before\ncli forum \"$FORUM\"\n// after\ncli forum \"${FORUM:?set FORUM to an openreview forum id}\"","handlingStrategy":"validation","validationCode":"function hasForumId(v) { return typeof v === 'string' && v.trim().length > 0; }\nif (!hasForumId(args.id)) { console.error('usage: cli id <forum-id>'); process.exit(2); }","typeGuard":"const isNonEmptyString = (v) => typeof v === 'string' && v.trim().length > 0;","tryCatchPattern":"try { const id = requireForumId(args.id); } catch (e) { if (e instanceof ArgumentError) { console.error(e.message); process.exit(2); } throw e; }","preventionTips":["Always supply the id argument; extract it from the forum URL's ?id= parameter.","Fail fast in scripts with ${VAR:?} parameter expansion.","Trim user input but reject empty before calling the command."],"tags":["validation","argument-error","missing-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}