{"record":{"id":"fe72922afb73d41a","repo":"badges/shields","slug":"resource-not-found-fe7292","errorCode":null,"errorMessage":"resource not found","messagePattern":"resource not found","errorType":"exception","errorClass":"NotFound","httpStatus":404,"severity":"error","filePath":"services/voxelshop/voxelshop-rating.service.js","lineNumber":53,"sourceCode":"  static defaultBadgeData = {\n    label: 'rating',\n  }\n\n  static render({ format, total, average }) {\n    const message =\n      format === 'stars'\n        ? starRating(average)\n        : `${average}/5 (${metric(total)})`\n    return {\n      message,\n      color: floorCount(average, 2, 3, 4),\n    }\n  }\n\n  async handle({ format, resourceId }) {\n    const { response } = await this.fetch({ resourceId })\n    if (!response.resource) {\n      throw new NotFound()\n    }\n    return this.constructor.render({\n      format,\n      total: response.resource.reviews.count,\n      average: response.resource.reviews.stars.toFixed(2),\n    })\n  }\n}\n","sourceCodeStart":35,"sourceCodeEnd":62,"githubUrl":"https://github.com/badges/shields/blob/766fd8bc89a90b8534dc573ab72dec30215ab1ec/services/voxelshop/voxelshop-rating.service.js#L35-L62","documentation":"The voxelshop rating service throws NotFound when the upstream VoxelShop API responds but contains no 'resource' object for the given resourceId. This means VoxelShop has no product/resource matching the requested id, so no review count or average rating can be rendered.","triggerScenarios":"Calling the badge with a resourceId that does not exist in VoxelShop's catalog, or a resourceId that has been deleted/renamed, causing response.resource to be undefined.","commonSituations":"Typo in the product id, product removed from the shop, using an internal id instead of the shop-facing resource id, or the shop itself being offline/decommissioned.","solutions":["Verify the resourceId by opening the product page on voxelshop.com and confirming the id in its URL","Re-check spelling and casing of the resourceId parameter","If the product was removed, remove or update the badge","Confirm the VoxelShop API is reachable and still serving that resource"],"exampleFix":"// before\nhandle({ resourceId: 'voxel-atlas-2' })\n// after\nhandle({ resourceId: 'voxel-atlas' }) // corrected id verified on the product page","handlingStrategy":"try-catch","validationCode":"// verify the resource exists before rendering\nconst res = await fetch(`https://voxelshop.com/api/resource/${resourceId}`).then(r => r.json())\nif (!res?.resource) throw new Error(`Unknown VoxelShop resourceId: ${resourceId}`)","typeGuard":"function hasResource(r) { return r != null && typeof r === 'object' && r.resource != null && r.resource.reviews != null }","tryCatchPattern":"try {\n  const badge = await voxelshopRating.handle({ format, resourceId })\n} catch (e) {\n  if (e instanceof NotFound) {\n    // render a fallback badge, e.g. 'voxelshop | not found'\n  } else throw e\n}","preventionTips":["Copy the resourceId directly from the product page URL, never type it by hand","Check the badge after first render — a 404-style badge means the id is wrong","Periodically validate that linked products still exist in the shop"],"tags":["http-404","not-found","upstream-api","badge"],"backgroundTag":"resource-not-found","analyzedSha":"766fd8bc89a90b8534dc573ab72dec30215ab1ec","analyzedAt":"2026-08-30T01:40:27.499Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}