{"record":{"id":"2a712c5ebc5f4c3e","repo":"jackwener/OpenCLI","slug":"crates-crate-name-is-required-e-g-serde-toki","errorCode":null,"errorMessage":"crates crate name is required (e.g. \"serde\", \"tokio\")","messagePattern":"crates crate name is required \\(e\\.g\\. \"serde\", \"tokio\"\\)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/crates/utils.js","lineNumber":18,"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);\n    if (!Number.isInteger(n) || n <= 0) {\n        throw new ArgumentError(`crates ${label} must be a positive integer`);\n    }\n    if (n > maxValue) {\n        throw new ArgumentError(`crates ${label} must be <= ${maxValue}`);\n    }","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/crates/utils.js#L1-L36","documentation":"requireCrateName enforces that a crate name is present before validating its format; empty values get this dedicated message with examples ('serde', 'tokio'). It exists so the common 'forgot the name' case produces a more helpful error than the format-failure message.","triggerScenarios":"Calling `crates crate` (or anything that calls requireCrateName) with name === '', '   ', null, or undefined — typically when the positional/flag argument was omitted entirely.","commonSituations":"Running the CLI interactively and forgetting the crate argument, scripting with an unset variable, or a wrapper passing undefined when a lookup fails.","solutions":["Pass a crate name, e.g. `crates crate serde`.","In scripts, default or assert the variable before calling: if (!name) fail fast.","Use `crates search <keyword>` first if you do not know the exact name.","Wrap calls in a try/catch on ArgumentError to surface usage help."],"exampleFix":"// before\nawait cli.crates.crate({ name: undefined });\n// after\nawait cli.crates.crate({ name: 'tokio' });","handlingStrategy":"validation","validationCode":"function requireName(value) {\n  const s = String(value ?? '').trim();\n  if (!s) throw new Error('crate name is required (e.g. \"serde\", \"tokio\")');\n  return s;\n}","typeGuard":"function hasCrateName(v) {\n  return typeof v === 'string' && v.trim().length > 0;\n}","tryCatchPattern":"try {\n  await cli.crates.crate({ name });\n} catch (e) {\n  if (e instanceof ArgumentError && e.message.includes('crate name is required')) {\n    console.error('Usage: crates crate <name>');\n  } else throw e;\n}","preventionTips":["Include the crate name in scripted invocations; never rely on unset variables.","Default interactive prompts to well-known examples to avoid empty submits.","Validate arguments at the CLI boundary before dispatching."],"tags":["argument-validation","missing-argument","crates-io"],"backgroundTag":"missing-required-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}