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
- Inspect the actual redirect Location header (curl -I) and compare it to the expected `<module>-<version>.opm` pattern.
- Verify the moduleName in the badge URL exactly matches the published artifact filename prefix.
- 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
- Inspect the actual Location header with curl -I when the badge breaks
- Watch for upstream artifact-naming changes on opm.openresty.org
- Guard regex extractions with null checks instead of indexing match()[1] directly
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
- metadata in unexpected format
- unparseable svg response
- unparseable toml response
- unparseable xml response
- unparseable yaml response
AI-assisted analysis of badges/shields@766fd8bc89 (2026-08-30).
Data as JSON: /api/errors/9bcba0f9589aa5d0.
Report an issue: GitHub.