{"record":{"id":"322796ebab97a72a","repo":"jackwener/OpenCLI","slug":"rubygems-label-cannot-be-empty","errorCode":null,"errorMessage":"rubygems ${label} cannot be empty","messagePattern":"rubygems (.+?) cannot be empty","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/rubygems/utils.js","lineNumber":17,"sourceCode":"// Shared helpers for the RubyGems.org adapters.\n//\n// Hits the public, unauthenticated `rubygems.org/api/v1` REST endpoints. No\n// auth required for read-only metadata; the API is friendly to anonymous CLI\n// traffic. Gem names follow the RubyGems convention: lowercase ASCII +\n// `-_.`, 1-100 chars, must start with a letter or digit.\nimport { ArgumentError, CommandExecutionError, EmptyResultError } from '@jackwener/opencli/errors';\n\nexport const GEMS_BASE = 'https://rubygems.org/api/v1';\nconst UA = 'opencli-rubygems-adapter (+https://github.com/jackwener/opencli)';\n\n// RubyGems gem name pattern (mirrors the rubygems-server validation).\nconst GEM_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;\n\nexport function requireString(value, label) {\n    const s = String(value ?? '').trim();\n    if (!s) throw new ArgumentError(`rubygems ${label} cannot be empty`);\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(`rubygems ${label} must be a positive integer`);\n    }\n    if (n > maxValue) {\n        throw new ArgumentError(`rubygems ${label} must be <= ${maxValue}`);\n    }\n    return n;\n}\n\nexport function requireGemName(value) {\n    const s = String(value ?? '').trim();\n    if (!s) {","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/rubygems/utils.js#L1-L35","documentation":"requireString in clis/rubygems/utils.js coerces its argument to a trimmed string and throws ArgumentError('rubygems ${label} cannot be empty') when the result is empty. It is the guard used for required string arguments such as the search query, so the library fails fast instead of issuing a doomed API call.","triggerScenarios":"requireString(value, label) receives null, undefined, an empty string, or whitespace-only input; e.g. search({ query: '' }) or search({}) where query is undefined (label 'query').","commonSituations":"Forgetting to pass the query flag on the CLI (`opencli rubygems search` with no argument); a shell variable holding the query being unset/empty; passing an empty array/object that stringifies to ''. ","solutions":["Supply a non-empty value for the flagged argument, e.g. `opencli rubygems search --query rails`.","Check the variable feeding the argument: `echo \"$QUERY\"` to confirm it is not empty before invoking.","In calling code, default or prompt for the value: args.query ||= (await prompt('query:'))."],"exampleFix":"// before\nawait search({ query: '' }); // throws\n\n// after\nconst query = (process.argv[2] || '').trim();\nif (!query) throw new Error('usage: rubygems search <query>');\nawait search({ query });","handlingStrategy":"validation","validationCode":"function requireQuery(q) {\n  const s = String(q ?? '').trim();\n  if (!s) throw new Error('query must be a non-empty string');\n  return s;\n}","typeGuard":"function isNonEmptyString(v) {\n  return typeof v === 'string' && v.trim().length > 0;\n}","tryCatchPattern":"try {\n  await search({ query: args.query });\n} catch (e) {\n  if (e instanceof ArgumentError && /cannot be empty/.test(e.message)) {\n    console.error('Provide a search term, e.g. --query rails');\n    process.exitCode = 2;\n  } else throw e;\n}","preventionTips":["Always validate CLI args with a usage guard before invoking library calls.","Check shell variables for emptiness (`: \"${QUERY:?query required}\"`) in scripts.","Trim user input before passing it on."],"tags":["validation","argument-error","cli-input","rubygems"],"backgroundTag":"missing-required-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}