{"record":{"id":"72376966f9656198","repo":"badges/shields","slug":"tag-not-found-723769","errorCode":null,"errorMessage":"tag not found","messagePattern":"tag not found","errorType":"exception","errorClass":"NotFound","httpStatus":404,"severity":"error","filePath":"services/npm/npm-version.service.js","lineNumber":85,"sourceCode":"  }\n\n  async handle(namedParams, queryParams) {\n    const { scope, packageName, tag, registryUrl } =\n      this.constructor.unpackParams(namedParams, queryParams)\n\n    const slug =\n      scope === undefined\n        ? packageName\n        : this.constructor.encodeScopedPackage({ scope, packageName })\n\n    const packageData = await this._requestJson({\n      schema,\n      url: `${registryUrl}/-/package/${slug}/dist-tags`,\n      httpErrors: { 404: 'package not found' },\n    })\n\n    if (tag && !(tag in packageData)) {\n      throw new NotFound({ prettyMessage: 'tag not found' })\n    }\n\n    return this.constructor.render({\n      tag,\n      version: packageData[tag || 'latest'],\n    })\n  }\n}\n","sourceCodeStart":67,"sourceCodeEnd":94,"githubUrl":"https://github.com/badges/shields/blob/766fd8bc89a90b8534dc573ab72dec30215ab1ec/services/npm/npm-version.service.js#L67-L94","documentation":"The npm version service fetches a package's dist-tags document from `${registryUrl}/-/package/${slug}/dist-tags` and throws NotFound 'tag not found' when a tag parameter was supplied but is not a key in that object. This is an explicit `in` check on the dist-tags map, so it precisely detects unknown tags; a 404 from the registry is separately mapped to 'package not found'.","triggerScenarios":"GET badge with ?tag=foo where foo is not in the package's dist-tags response; querying a package on a custom registry where that tag was never published; slug (scoped package encoding) fine but tag misspelled.","commonSituations":"Using tags from one registry against another registry/mirror; tags renamed (e.g. 'next' -> 'beta') breaking old badge URLs; case-sensitive tag mismatch.","solutions":["Fetch the dist-tags endpoint and pick an existing key for the ?tag parameter","Remove ?tag to use the implicit 'latest' entry","Publish/point the tag on the target registry: `npm dist-tag add --registry <url>`","Correct the tag spelling/casing in the badge URL"],"exampleFix":"// before\n/npm/v/lodash/badge.svg?tag=stable   // 'stable' not in dist-tags\n// after\n/npm/v/lodash/badge.svg?tag=latest","handlingStrategy":"validation","validationCode":"const distTags = await fetch(`${registry}/-/package/${encodeURIComponent(pkg).replace('%2F', '/')}/dist-tags`).then(r => r.json())\nif (tag && !(tag in distTags)) {\n  throw new Error(`tag '${tag}' not found; available: ${Object.keys(distTags).join(', ')}`)\n}","typeGuard":"function hasTag(distTags, tag) {\n  return typeof distTags === 'object' && distTags !== null && (tag ? tag in distTags : 'latest' in distTags)\n}","tryCatchPattern":"try {\n  return await versionBadge({ pkg, tag })\n} catch (e) {\n  if (e instanceof NotFound && e.message === 'tag not found') {\n    const available = await fetchDistTags(pkg)\n    throw new Error(`tag '${tag}' not found. Available: ${Object.keys(available).join(', ')}`)\n  }\n  throw e\n}","preventionTips":["Fetch and display available dist-tags to users instead of guessing tag names","Use the same registry for tag discovery and badge rendering — tags differ per registry","Watch for tag renames upstream and update badge URLs accordingly","For scoped packages, encode the name correctly in the dist-tags URL slug"],"tags":["npm","not-found","dist-tags","registry"],"backgroundTag":"dist-tag-not-found","analyzedSha":"766fd8bc89a90b8534dc573ab72dec30215ab1ec","analyzedAt":"2026-08-30T01:40:27.499Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}