{"record":{"id":"f3e2a3256bc6783e","repo":"badges/shields","slug":"this-constructor-type-not-found","errorCode":null,"errorMessage":"${this.constructor.type} not found","messagePattern":"(.+?) not found","errorType":"exception","errorClass":"NotFound","httpStatus":404,"severity":"error","filePath":"services/youtube/youtube-base.js","lineNumber":90,"sourceCode":"        {\n          schema,\n          url: `https://www.googleapis.com/youtube/v3/${this.constructor.type}s`,\n          options: {\n            searchParams: { id, part: 'statistics' },\n          },\n          httpErrors: {\n            400: `${this.constructor.type} not found`,\n          },\n        },\n      ),\n    )\n  }\n\n  async handle({ channelId, videoId }) {\n    const id = channelId || videoId\n    const json = await this.fetch({ id })\n    if (json.pageInfo.totalResults === 0) {\n      throw new NotFound({\n        prettyMessage: `${this.constructor.type} not found`,\n      })\n    }\n    const statistics = json.items[0].statistics\n    return this.constructor.render({ statistics, id })\n  }\n}\n\nclass YouTubeVideoBase extends YouTubeBase {\n  static type = 'video'\n}\n\nclass YouTubeChannelBase extends YouTubeBase {\n  static type = 'channel'\n}\n\nexport { description, YouTubeVideoBase, YouTubeChannelBase }\n","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/badges/shields/blob/766fd8bc89a90b8534dc573ab72dec30215ab1ec/services/youtube/youtube-base.js#L72-L108","documentation":"The YouTube base service throws NotFound with message '<type> not found' when the YouTube Data API reports pageInfo.totalResults === 0 for the given channelId or videoId, meaning no channel/video matched the id. The API call itself succeeded (key valid, quota OK).","triggerScenarios":"Calling a youtube badge (views, likes, comments) with a channelId or videoId that returns zero results — deleted resource, wrong id format, or an id for a different resource type.","commonSituations":"Channel deleted or terminated, using a custom handle (e.g. @name) instead of the numeric/channel id, video made private or removed, swapping channelId and videoId parameters, region-blocked resources.","solutions":["Verify the id: for channels use the UC... channelId from the channel page source (or via a handle-to-id lookup), not the @handle or vanity URL","Open the video/channel URL to confirm it still exists and is public","Check that the value is passed in the correct parameter (channelId vs videoId)","If the resource was deleted or made private, remove or update the badge"],"exampleFix":"// before\nhandle({ channelId: '@MyChannel' })\n// after\nhandle({ channelId: 'UC_x5XG1OV2P6uZZ5FSM9Ttw' })","handlingStrategy":"validation","validationCode":"// resolve a YouTube handle to a channelId and verify existence before rendering\nconst lookup = await fetch(`https://www.googleapis.com/youtube/v3/channels?part=id&forHandle=${handle}&key=${KEY}`).then(r => r.json())\nif (lookup.pageInfo.totalResults === 0) throw new Error('channel not found');","typeGuard":"function channelExists(json) { return json?.pageInfo?.totalResults > 0 && Array.isArray(json.items) && json.items.length > 0 }","tryCatchPattern":"try {\n  const badge = await ytService.handle({ channelId, videoId })\n} catch (e) {\n  if (e.message.endsWith('not found')) {\n    // render 'youtube | not found'\n  } else throw e\n}","preventionTips":["Use the UC... channelId extracted from the channel page, never the @handle or vanity name","Confirm the video/channel is public and not deleted before adding a badge","Keep channelId and videoId in their correct parameters and validate with the API's channels/videos endpoint first"],"tags":["not-found","youtube","id-mismatch","upstream-api"],"backgroundTag":"resource-not-found","analyzedSha":"766fd8bc89a90b8534dc573ab72dec30215ab1ec","analyzedAt":"2026-08-30T01:40:27.499Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}