{"record":{"id":"b9121472a0614c2f","repo":"jackwener/OpenCLI","slug":"weread-official-label-cannot-be-empty","errorCode":null,"errorMessage":"weread-official: ${label} cannot be empty","messagePattern":"weread-official: (.+?) cannot be empty","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/weread-official/utils.js","lineNumber":247,"sourceCode":"    return `weread://reading?bId=${bid}`;\n}\n\n/**\n * Split a WeRead `range` field (\"900-2004\") into `{rangeStart, rangeEnd}`.\n * Returns empty strings when the input is missing/malformed.\n */\nexport function parseRange(range) {\n    const text = String(range ?? '').trim();\n    const match = text.match(/^(\\d+)-(\\d+)$/);\n    if (!match) return { rangeStart: '', rangeEnd: '' };\n    return { rangeStart: match[1], rangeEnd: match[2] };\n}\n\n// ── Argument validation ─────────────────────────────────────────────────────\n\nexport function requireText(value, label) {\n    const text = String(value ?? '').trim();\n    if (!text) throw new ArgumentError(`weread-official: ${label} cannot be empty`);\n    return text;\n}\n\nexport function requireBookId(value, label = 'bookId') {\n    const text = requireText(value, label);\n    if (!/^[A-Za-z0-9_-]+$/.test(text)) {\n        throw new ArgumentError(`weread-official: ${label} contains invalid characters`, 'Pass a bookId from `weread-official search`.');\n    }\n    return text;\n}\n\nexport function requirePositiveInt(value, label, { defaultValue, max } = {}) {\n    if (value === undefined || value === null || value === '') {\n        if (defaultValue === undefined) {\n            throw new ArgumentError(`weread-official: ${label} is required`);\n        }\n        return defaultValue;\n    }","sourceCodeStart":229,"sourceCodeEnd":265,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/weread-official/utils.js#L229-L265","documentation":"requireText trims its input and throws ArgumentError if nothing remains. Every text parameter (query, keyword, note text) passes through it, guaranteeing the gateway never receives empty strings (which the gateway would silently drop from the flattened body).","triggerScenarios":"Passing '' , '   ', null, or undefined to requireText-backed helpers like keyword or text; a CLI flag provided but empty (e.g. --query \"\"); a variable that was never assigned.","commonSituations":"Empty shell variable expansion ($QUERY unset); copy-paste of whitespace-only text; interactive prompt cancelled leaving empty input; script reading an empty file as the query.","solutions":["Supply a non-empty value for the flagged parameter.","Check shell variables with `echo \"-${QUERY}-\"` to spot unset/empty values.","Guard with requireText or a length check at the entry point of your script.","Remove the empty flag rather than passing an empty value."],"exampleFix":"// before\nconst query = process.env.QUERY ?? '';\nawait keyword(query);\n// after\nconst query = process.env.QUERY;\nif (!query || !query.trim()) throw new Error('QUERY env var is required');\nawait keyword(query);","handlingStrategy":"validation","validationCode":"function requireNonEmpty(v, label) {\n  const t = String(v ?? '').trim();\n  if (!t) throw new Error(`${label} must be a non-empty string`);\n  return t;\n}\nconst query = requireNonEmpty(process.env.QUERY, 'QUERY');","typeGuard":"const isNonEmptyText = (v) => typeof v === 'string' && v.trim().length > 0;","tryCatchPattern":"try {\n  return await keyword(rawQuery);\n} catch (e) {\n  if (e instanceof ArgumentError && /cannot be empty/.test(e.message)) {\n    console.error(`Empty ${label} — check the flag/env var feeding it`);\n    process.exitCode = 2;\n  } else throw e;\n}","preventionTips":["Quote shell variables and check them before interpolation","Use the requireText helper at every CLI entry point","Reject empty flags explicitly in argument parsers","Trim inputs early and fail with the parameter label"],"tags":["argument-validation","empty-input"],"backgroundTag":"empty-required-parameter","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}