badges/shields · error · InvalidResponse

invalid json response

Error message

invalid json response

What it means

Thrown when the resolved latestVersion does not map to an entry in json.versions, leaving packageData undefined so the subsequent schema validation path is invalid. The service wraps the versions lookup in try/catch and converts the failure into InvalidResponse 'invalid json response'. In practice this means the registry metadata is inconsistent: a dist-tag points at a version that is not present in the versions map.

Source

Thrown at services/npm/npm-base.js:144

      url,
      httpErrors: { 404: 'package not found' },
    })

    let packageData
    if (scope === undefined && tag === undefined) {
      packageData = json
    } else {
      const registryTag = tag || 'latest'
      let latestVersion
      try {
        latestVersion = json['dist-tags'][registryTag]
      } catch (e) {
        throw new NotFound({ prettyMessage: 'tag not found' })
      }
      try {
        packageData = json.versions[latestVersion]
      } catch (e) {
        throw new InvalidResponse({ prettyMessage: 'invalid json response' })
      }
    }

    return this.constructor._validate(packageData, packageDataSchema)
  }

  async fetch({
    registryUrl,
    scope,
    packageName,
    schema,
    abbreviated = false,
  }) {
    registryUrl = registryUrl || this.constructor.defaultRegistryUrl
    let url

    if (scope === undefined) {
      url = `${registryUrl}/${packageName}`

View on GitHub (pinned to 766fd8bc89)

Solutions

  1. Retry against the official registry (registry.npmjs.org) to bypass a stale mirror/proxy cache
  2. Run `npm view <pkg>` and compare dist-tags vs versions; republish or `npm dist-tag add` to fix a dangling tag if you own the package
  3. Purge the mirror/proxy cache for the package metadata
  4. If servicing code, add an explicit check `if (!packageData) throw new InvalidResponse(...)` instead of relying on try/catch

Example fix

// before
try { packageData = json.versions[latestVersion] } catch (e) { throw new InvalidResponse(...) }
// after
packageData = json.versions && latestVersion ? json.versions[latestVersion] : undefined
if (!packageData) throw new InvalidResponse({ prettyMessage: 'invalid json response' })
Defensive patterns

Strategy: try-catch

Validate before calling

const meta = await fetch(`${registry}/${pkg}`).then(r => r.json())
const latest = meta && meta['dist-tags'] && meta['dist-tags'].latest
if (!latest || !meta.versions || !(latest in meta.versions)) {
  throw new Error(`registry metadata inconsistent: tag '${latest}' missing from versions`)
}

Type guard

function hasConsistentMetadata(json) {
  const v = json && json['dist-tags'] && json['dist-tags'].latest
  return Boolean(v && json.versions && json.versions[v])
}

Try / catch

try {
  return await npmBadge({ pkg })
} catch (e) {
  if (e instanceof InvalidResponse && e.message === 'invalid json response') {
    // likely a stale mirror; retry official registry
    return npmBadge({ pkg, registry: 'https://registry.npmjs.org' })
  }
  throw e
}

Prevention

When it happens

Trigger: Registry JSON where dist-tags references a version missing from json.versions (truncated/corrupted metadata); a proxy/mirror returning partial documents; json.versions absent entirely so the property access path breaks.

Common situations: Using a stale or misbehaving npm mirror (e.g. corporate proxy) whose metadata cache is inconsistent; third-party registries with non-standard metadata; race during package publish/unpublish where tags and versions diverge.

Understand the failure class

Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.

Related errors


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