badges/shields · error · InvalidResponse

version invalid

Error message

version invalid

What it means

After obtaining the OPM redirect location, the service extracts the version via the regex `${moduleName}-(.+).opm`. If the match succeeds structurally but yields no capture group — or the URL does not follow the expected `<moduleName>-<version>.opm` naming — it throws InvalidResponse, meaning upstream returned something the service cannot parse into a version.

Source

Thrown at services/opm/opm-version.service.js:56

        method: 'HEAD',
        searchParams: {
          account: user,
          name: moduleName,
        },
      },
      httpErrors: {
        404: 'module not found',
      },
    })

    // TODO: set followRedirect to false and intercept 302 redirects
    const location = res.redirectUrls[0].toString()
    if (!location) {
      throw new NotFound({ prettyMessage: 'module not found' })
    }
    const version = location.match(`${moduleName}-(.+).opm`)[1]
    if (!version) {
      throw new InvalidResponse({ prettyMessage: 'version invalid' })
    }
    return version
  }

  async handle({ user, moduleName }) {
    const version = await this.fetch({ user, moduleName })

    return renderVersionBadge({ version })
  }
}

View on GitHub (pinned to 766fd8bc89)

Solutions

  1. Inspect the actual redirect Location header (curl -I) and compare it to the expected `<module>-<version>.opm` pattern.
  2. Verify the moduleName in the badge URL exactly matches the published artifact filename prefix.
  3. If the upstream filename scheme changed, the service regex needs updating — report/patch the service.

Example fix

// before
const version = location.match(`${moduleName}-(.+).opm`)[1]
// after
const m = location.match(`${moduleName}-(.+?)\.opm`)
if (!m) throw new InvalidResponse({ prettyMessage: 'version invalid' })
const version = m[1]
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check the redirect target matches the expected artifact naming
const loc = res.redirectUrls[0] && res.redirectUrls[0].toString()
if (!loc || !new RegExp(`${moduleName}-(.+)\\.opm`).test(loc)) {
  throw new Error('OPM redirect URL does not contain a parseable version')
}

Type guard

function hasParseableVersion(location, moduleName) {
  const m = location && location.match(`${moduleName}-(.+).opm`)
  return Boolean(m && m[1])
}

Try / catch

try {
  const version = await getOpmVersion(user, moduleName)
} catch (e) {
  if (e.message === 'version invalid') {
    // treat as upstream format change: fall back to 'unknown' badge
  } else { throw e }
}

Prevention

When it happens

Trigger: The redirect Location URL exists but does not match `${moduleName}-(.+).opm` as expected (regex fails so `match(...)[1]` throws, or capture is empty), e.g. a changed filename scheme on the opm server.

Common situations: Upstream renaming of .opm artifacts, modules whose names embed the version differently, or a redirect to an HTML error page whose URL happens to be present but not a module file.

Related errors


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