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

  1. Broaden the search query (e.g. 'rail' instead of a full name) and retry.
  2. Check connectivity to rubygems.org (`curl -s 'https://rubygems.org/api/v1/search.json?query=rails'`).
  3. 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

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


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/bae65af0ce64990f. Report an issue: GitHub.