badges/shields · error · InvalidParameter

version downloads requires a version

Error message

version downloads requires a version

What it means

Thrown in GemDownloadsService.handle when the 'dv' (downloads per version) variant is requested but no version parameter is supplied. The dv path semantically requires an explicit version, so a missing version is rejected with InvalidParameter 'version downloads requires a version'.

Source

Thrown at services/gem/gem-downloads.service.js:126

  }

  async fetchDownloadCountForGem({ gem }) {
    const { downloads: totalDownloads, version_downloads: versionDownloads } =
      await this._requestJson({
        url: `https://rubygems.org/api/v1/gems/${gem}.json`,
        schema: gemSchema,
        httpErrors: {
          404: 'gem not found',
        },
      })
    return { totalDownloads, versionDownloads }
  }

  async handle({ variant, gem, version }) {
    let downloads
    if (variant === 'dv') {
      if (!version) {
        throw new InvalidParameter({
          prettyMessage: 'version downloads requires a version',
        })
      }
      if (version !== 'stable' && !semver.valid(version)) {
        throw new InvalidParameter({
          prettyMessage: 'version should be "stable" or valid semver',
        })
      }
      downloads = await this.fetchDownloadCountForVersion({ gem, version })
    } else {
      const { totalDownloads, versionDownloads } =
        await this.fetchDownloadCountForGem({ gem, variant })
      downloads = variant === 'dtv' ? versionDownloads : totalDownloads
    }
    return this.constructor.render({ variant, version, downloads })
  }
}

View on GitHub (pinned to 766fd8bc89)

Solutions

  1. Add the version segment: /gem/dv/<gem>/<version>
  2. Use the plain downloads badge (/gem/dt/<gem> or /gem/<gem>) if you do not want a specific version
  3. Pass version 'stable' if you want the stable version's downloads

Example fix

// before
/gem/dv/mygem
// after
/gem/dv/mygem/1.2.3
Defensive patterns

Strategy: validation

Validate before calling

if (variant === 'dv' && !version) { throw new Error('dv variant requires a version: /gem/dv/<gem>/<version>'); }

Type guard

const isDvRequest = (q) => q?.variant === 'dv' && typeof q?.version === 'string' && q.version.length > 0;

Try / catch

try { return await gemBadge({ variant, gem, version }); } catch (e) { if (String(e.message).includes('requires a version')) { return gemBadge({ variant: 'dt', gem }); } throw e; }

Prevention

When it happens

Trigger: GET /gem/dv/<gem> — the variant is 'dv' but the version URL segment is absent, so handle({ variant: 'dv', gem, version: undefined }).

Common situations: Users copying the total-downloads badge URL (/gem/dt/ or /gem/) but keeping or mixing variant tokens, omitting the version segment for dv; documentation confusion between dt (total) and dv (per-version).

Understand the failure class

Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.

Related errors


AI-assisted analysis of badges/shields@766fd8bc89 (2026-08-30). Data as JSON: /api/errors/482bc6897690c1a7. Report an issue: GitHub.