jackwener/OpenCLI · warning · EmptyResultError
rubygems search
Error message
rubygems search
What it means
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.
Source
Thrown at clis/rubygems/search.js:30
name: 'search',
access: 'read',
description: 'Search RubyGems.org gems by keyword',
domain: 'rubygems.org',
strategy: Strategy.PUBLIC,
browser: false,
args: [
{ name: 'query', positional: true, required: true, help: 'Search keyword (e.g. "rails", "redis")' },
{ name: 'limit', type: 'int', default: 30, help: 'Max gems (1-100, single RubyGems page)' },
],
columns: ['rank', 'gem', 'version', 'downloads', 'license', 'authors', 'info', 'url'],
func: async (args) => {
const query = requireString(args.query, 'query');
const limit = requireBoundedInt(args.limit, 30, 100);
const url = `${GEMS_BASE}/search.json?query=${encodeURIComponent(query)}&page=1`;
const body = await gemsFetch(url, 'rubygems search');
const list = Array.isArray(body) ? body : [];
if (!list.length) {
throw new EmptyResultError('rubygems search', `No gems matched "${query}".`);
}
return list.slice(0, limit).map((g, i) => {
const name = String(g.name ?? '').trim();
const licenses = Array.isArray(g.licenses) ? g.licenses.filter(Boolean).join(', ') : '';
return {
rank: i + 1,
gem: name,
version: String(g.version ?? '').trim(),
downloads: g.downloads != null ? Number(g.downloads) : null,
license: licenses,
authors: String(g.authors ?? '').trim(),
info: String(g.info ?? '').trim(),
url: name ? `https://rubygems.org/gems/${name}` : '',
};
});
},
});
View on GitHub (pinned to 49907e53dc)
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.
Example fix
// before
search({ query: 'sidekq' });
// after
try {
search({ query: 'sidekq' });
} catch (e) {
// EmptyResultError: retry with corrected/partial query
search({ query: 'sidekiq' });
} Defensive patterns
Strategy: fallback
Validate before calling
const query = (args.query ?? '').trim();
if (!query) {
console.error('usage: rubygems search <query>');
process.exit(1);
} Type guard
function isNonEmptyString(v) {
return typeof v === 'string' && v.trim().length > 0;
} Try / catch
try {
const gems = await search({ query });
} catch (e) {
if (e instanceof EmptyResultError) {
console.log(`No gems matched "${query}" — try a shorter prefix.`);
} else throw e;
} Prevention
- 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.
When it happens
Trigger: Calling the rubygems search command with a query that matches no gems (EmptyResultError path), or gemsFetch wrapping a network failure with this label.
Common situations: Typo in gem name or extremely specific query; rubygems.org unreachable (offline, DNS failure, blocked network); rubygems.org returning an unexpected non-array payload.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- aibase news
- archive search request failed: ${error?.message || error}
- archive search returned malformed JSON: ${error?.message ||
- coingecko categories request failed: ${err?.message ?? err}
- coingecko trending request failed: ${error?.message || error
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/bae65af0ce64990f.
Report an issue: GitHub.