{"record":{"id":"bae65af0ce64990f","repo":"jackwener/OpenCLI","slug":"rubygems-search","errorCode":null,"errorMessage":"rubygems search","messagePattern":"rubygems search","errorType":"exception","errorClass":"EmptyResultError","httpStatus":null,"severity":"warning","filePath":"clis/rubygems/search.js","lineNumber":30,"sourceCode":"    name: 'search',\n    access: 'read',\n    description: 'Search RubyGems.org gems by keyword',\n    domain: 'rubygems.org',\n    strategy: Strategy.PUBLIC,\n    browser: false,\n    args: [\n        { name: 'query', positional: true, required: true, help: 'Search keyword (e.g. \"rails\", \"redis\")' },\n        { name: 'limit', type: 'int', default: 30, help: 'Max gems (1-100, single RubyGems page)' },\n    ],\n    columns: ['rank', 'gem', 'version', 'downloads', 'license', 'authors', 'info', 'url'],\n    func: async (args) => {\n        const query = requireString(args.query, 'query');\n        const limit = requireBoundedInt(args.limit, 30, 100);\n        const url = `${GEMS_BASE}/search.json?query=${encodeURIComponent(query)}&page=1`;\n        const body = await gemsFetch(url, 'rubygems search');\n        const list = Array.isArray(body) ? body : [];\n        if (!list.length) {\n            throw new EmptyResultError('rubygems search', `No gems matched \"${query}\".`);\n        }\n        return list.slice(0, limit).map((g, i) => {\n            const name = String(g.name ?? '').trim();\n            const licenses = Array.isArray(g.licenses) ? g.licenses.filter(Boolean).join(', ') : '';\n            return {\n                rank: i + 1,\n                gem: name,\n                version: String(g.version ?? '').trim(),\n                downloads: g.downloads != null ? Number(g.downloads) : null,\n                license: licenses,\n                authors: String(g.authors ?? '').trim(),\n                info: String(g.info ?? '').trim(),\n                url: name ? `https://rubygems.org/gems/${name}` : '',\n            };\n        });\n    },\n});\n","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/rubygems/search.js#L12-L48","documentation":"In clis/rubygems/search.js the search command throws an EmptyResultError with the message 'rubygems search' when the gemsFetch call to rubygems.org /search.json fails at the transport level, or when the response body is not an array. In the source shown, the label 'rubygems search' is passed to gemsFetch and also used for the EmptyResultError raised when no gems matched the query.","triggerScenarios":"Calling the rubygems search command with a query that matches no gems (EmptyResultError path), or gemsFetch wrapping a network failure with this label.","commonSituations":"Typo in gem name or extremely specific query; rubygems.org unreachable (offline, DNS failure, blocked network); rubygems.org returning an unexpected non-array payload.","solutions":["Broaden the search query (e.g. 'rail' instead of a full name) and retry.","Check connectivity to rubygems.org (`curl -s 'https://rubygems.org/api/v1/search.json?query=rails'`).","Catch EmptyResultError and offer suggestions rather than treating it as a hard failure."],"exampleFix":"// before\nsearch({ query: 'sidekq' });\n\n// after\ntry {\n  search({ query: 'sidekq' });\n} catch (e) {\n  // EmptyResultError: retry with corrected/partial query\n  search({ query: 'sidekiq' });\n}","handlingStrategy":"fallback","validationCode":"const query = (args.query ?? '').trim();\nif (!query) {\n  console.error('usage: rubygems search <query>');\n  process.exit(1);\n}","typeGuard":"function isNonEmptyString(v) {\n  return typeof v === 'string' && v.trim().length > 0;\n}","tryCatchPattern":"try {\n  const gems = await search({ query });\n} catch (e) {\n  if (e instanceof EmptyResultError) {\n    console.log(`No gems matched \"${query}\" — try a shorter prefix.`);\n  } else throw e;\n}","preventionTips":["Prefer broader queries; RubyGems search matches names/descriptions loosely.","Always check connectivity to rubygems.org before bulk searches.","Treat EmptyResultError as a normal 'no matches' signal in scripts."],"tags":["rubygems","empty-results","network","cli"],"backgroundTag":"empty-result-set","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}