{"record":{"id":"d3b7c00b6d746684","repo":"jackwener/OpenCLI","slug":"label-is-required-d3b7c0","errorCode":null,"errorMessage":"${label} is required","messagePattern":"(.+?) is required","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/weread/book-search.js","lineNumber":54,"sourceCode":"function parseOptionalFiniteNumber(value) {\n    if (value == null || value === '')\n        return null;\n    const n = Number(value);\n    return Number.isFinite(n) ? n : null;\n}\n\nfunction parseHasMore(value) {\n    if (value === true || value === 1 || value === '1')\n        return true;\n    if (value === false || value === 0 || value === '0')\n        return false;\n    return null;\n}\n\nfunction normalizeRequiredString(value, label) {\n    const text = normalizeSearchText(value);\n    if (!text) {\n        throw new ArgumentError(`${label} is required`);\n    }\n    return text;\n}\n\nfunction parseWereadReaderUrl(value) {\n    let url;\n    try {\n        url = new URL(String(value || ''), WEREAD_WEB_ORIGIN);\n    }\n    catch {\n        return '';\n    }\n    const pathParts = url.pathname.split('/').filter(Boolean);\n    if (url.protocol !== 'https:' || url.hostname !== 'weread.qq.com' || pathParts[0] !== 'web' || pathParts[1] !== 'reader' || !pathParts[2]) {\n        return '';\n    }\n    if (pathParts.length !== 3) {\n        return '';","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/weread/book-search.js#L36-L72","documentation":"normalizeRequiredString normalizes a required text option (bookTarget/query) via normalizeSearchText and throws ArgumentError when the normalized result is empty. It means a mandatory input was missing, null, or whitespace-only after trimming.","triggerScenarios":"Running the command without the required --query (or book target) argument, or passing '' or '   ' — normalizeSearchText strips whitespace and falsy/empty results throw.","commonSituations":"Shell variables are unset or empty ($QUERY expands to nothing), quoting drops the argument, scripts forward an optional flag as an empty string, or users forget the positional argument.","solutions":["Provide a non-empty value for the labeled argument","Check for unset shell variables: use \"${QUERY:?QUERY is required}\" before invoking","Trim is not enough — pass real search text, not whitespace","Add an early check in your wrapper script before calling the CLI"],"exampleFix":"// before\nQUERY=\"\" weread book-search --query \"$QUERY\"\n// after\nQUERY=\"zen and the art\" weread book-search --query \"$QUERY\"","handlingStrategy":"validation","validationCode":"const query = (process.env.QUERY ?? '').trim();\nif (!query) {\n  console.error('QUERY is required and must be non-empty');\n  process.exit(2);\n}","typeGuard":"const isNonEmptyString = (v) => typeof v === 'string' && v.trim().length > 0;","tryCatchPattern":"try {\n  await runCommand(['book-search', '--query', query]);\n} catch (e) {\n  if (e instanceof ArgumentError && e.message.includes('is required')) {\n    console.error('Missing required argument: ' + e.message); process.exitCode = 2;\n  } else throw e;\n}","preventionTips":["Use ${VAR:?message} shell expansion to fail fast on unset variables","Trim and check inputs in wrapper scripts before delegating to the CLI","Never forward optional flags as empty strings; omit them instead"],"tags":["validation","cli-arguments","missing-required-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}