{"record":{"id":"31466c522a43cb9f","repo":"jackwener/OpenCLI","slug":"crates-label-cannot-be-empty","errorCode":null,"errorMessage":"crates ${label} cannot be empty","messagePattern":"crates (.+?) cannot be empty","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/crates/utils.js","lineNumber":12,"sourceCode":"// Shared helpers for the crates.io adapters.\nimport { ArgumentError, CommandExecutionError, EmptyResultError } from '@jackwener/opencli/errors';\n\nexport const CRATES_BASE = 'https://crates.io';\nconst UA = 'opencli-crates-adapter (+https://github.com/jackwener/opencli)';\n\n// crates.io crate names: 1-64 chars, ascii letters/digits/-_, must start with a letter.\nconst CRATE_NAME = /^[A-Za-z][A-Za-z0-9_-]{0,63}$/;\n\nexport function requireString(value, label) {\n    const s = String(value ?? '').trim();\n    if (!s) throw new ArgumentError(`crates ${label} cannot be empty`);\n    return s;\n}\n\nexport function requireCrateName(value) {\n    const s = String(value ?? '').trim();\n    if (!s) throw new ArgumentError('crates crate name is required (e.g. \"serde\", \"tokio\")');\n    if (!CRATE_NAME.test(s)) {\n        throw new ArgumentError(\n            `crates crate name \"${value}\" is not a valid crates.io name`,\n            'Names start with an ASCII letter, then 0-63 chars of letters / digits / \"_-\".',\n        );\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);","sourceCodeStart":1,"sourceCodeEnd":30,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/crates/utils.js#L1-L30","documentation":"requireString rejects empty/whitespace-only values for any labeled crates argument. If the stringified, trimmed value is empty it throws this ArgumentError with the label interpolated (e.g. 'crates query cannot be empty'). It guarantees downstream fetches never run with a blank query.","triggerScenarios":"Calling `crates search` with query set to '', '   ', null, or undefined; any CLI invocation where a required string flag was omitted or shell quoting collapsed it to nothing.","commonSituations":"Forgetting to pass --query in a script, environment-variable interpolation expanding to an empty string, an empty string in a config file, or shell word-splitting stripping whitespace-only arguments.","solutions":["Provide a non-empty query, e.g. --query \"serde\".","If the value comes from a variable or env var, check it is non-empty before invoking.","Pre-validate: if (!query?.trim()) throw/handle before calling the API.","Fix shell quoting so the flag is not collapsed to an empty argument."],"exampleFix":"// before\nconst q = process.env.SEARCH_TERM ?? ''; // '' when unset\nawait cli.crates.search({ query: q });\n// after\nconst q = process.env.SEARCH_TERM;\nif (!q || !q.trim()) throw new Error('SEARCH_TERM is required');\nawait cli.crates.search({ query: q.trim() });","handlingStrategy":"validation","validationCode":"function nonEmpty(value, label) {\n  const s = String(value ?? '').trim();\n  if (!s) throw new Error(`${label} cannot be empty`);\n  return s;\n}\nconst query = nonEmpty(process.argv.query, 'query');","typeGuard":"function isNonEmptyString(v) {\n  return typeof v === 'string' && v.trim().length > 0;\n}","tryCatchPattern":"try {\n  await cli.crates.search({ query });\n} catch (e) {\n  if (e instanceof ArgumentError && e.message.includes('cannot be empty')) {\n    console.error('Usage: crates search --query <term>');\n    process.exitCode = 2;\n  } else throw e;\n}","preventionTips":["Always pass required string flags explicitly; rely on defaults only where documented.","Check env vars/interpolations expand to non-empty before invoking.","Trim user input but reject empty after trimming.","In scripts, assert required args at the top of the script."],"tags":["argument-validation","empty-input","crates-io"],"backgroundTag":"missing-required-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}