{"record":{"id":"4aa084640e54a450","repo":"pear-devs/pear-desktop","slug":"playabilitystatus-status-errorscreen-reaso","errorCode":null,"errorMessage":"[${playabilityStatus.status}] ${errorScreen?.reason.text}: ${errorScreen?.subreason.text}","messagePattern":"\\[\\$\\{playabilityStatus\\.status\\}\\] \\$\\{errorScreen\\?\\.reason\\.text\\}: \\$\\{errorScreen\\?\\.subreason\\.text\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/plugins/downloader/main/index.ts","lineNumber":399,"sourceCode":"  let bypassedResult: YT.VideoInfo;\n  if (playabilityStatus?.status === 'LOGIN_REQUIRED') {\n    // Try to bypass the age restriction\n    bypassedResult = await getAndroidTvInfo(id);\n    playabilityStatus = bypassedResult.playability_status;\n\n    if (playabilityStatus?.status === 'LOGIN_REQUIRED') {\n      throw new Error(\n        `[${playabilityStatus.status}] ${playabilityStatus.reason}`,\n      );\n    }\n\n    info = bypassedResult;\n  }\n\n  if (playabilityStatus?.status === 'UNPLAYABLE') {\n    const errorScreen =\n      playabilityStatus.error_screen as YTNodes.PlayerErrorMessage | null;\n    throw new Error(\n      `[${playabilityStatus.status}] ${errorScreen?.reason.text}: ${errorScreen?.subreason.text}`,\n    );\n  }\n\n  const selectedPreset = config.selectedPreset ?? 'mp3 (256kbps)';\n  let presetSetting: Preset;\n  if (selectedPreset === 'Custom') {\n    presetSetting = config.customPresetSetting ?? DefaultPresetList['Custom'];\n  } else if (selectedPreset === 'Source') {\n    presetSetting = DefaultPresetList['Source'];\n  } else {\n    presetSetting = DefaultPresetList['mp3 (256kbps)'];\n  }\n\n  const downloadOptions: Types.FormatOptions = {\n    type: (await isPremium()) ? 'audio' : 'video+audio', // Audio, video or video+audio\n    quality: 'best', // Best, bestefficiency, 144p, 240p, 480p, 720p and so on.\n    format: 'any', // Media container format","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/pear-devs/pear-desktop/blob/1e2aac5706c870c93ed74ba8727ae8390d3b0fa5/src/plugins/downloader/main/index.ts#L381-L417","documentation":"When YouTube reports playability status UNPLAYABLE, the downloader throws an error embedding the status plus the PlayerErrorMessage reason/subreason from the error screen (e.g. '[UNPLAYABLE] Video unavailable: This video is not available in your country'). This is YouTube itself refusing to serve the track, not a plugin bug.","triggerScenarios":"Region-locked tracks; videos removed for copyright or policy reasons; purchased/ premium-only content; embedding-restricted or otherwise gated media — any case where playabilityStatus.status is 'UNPLAYABLE' after info fetch.","commonSituations":"Geo-restriction when downloading from another country; tracks deleted between listing and downloading; copyright takedowns; batch-archiving playlists where some entries have gone dark.","solutions":["Handle the error per-track in batch jobs (skip and log) instead of aborting the whole run","For geo-blocks, route through an appropriate region or accept the content is unavailable","Re-check the track in a browser to see the actual reason text; act accordingly (copyright = skip, region = different egress)","Keep the plugin updated since error-screen parsing can drift with API changes"],"exampleFix":"// before\nawait downloader.downloadSongFromId(id);\n\n// after\ntry {\n  await downloader.downloadSongFromId(id);\n} catch (e) {\n  if (e.message.startsWith('[UNPLAYABLE]')) log.warn(`Skipped ${id}: ${e.message}`);\n  else throw e;\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { await downloadSongFromId(id); } catch (e) {\n  if (/^\\[UNPLAYABLE\\]/.test(e.message)) { log.warn(`Skipped ${id}: ${e.message}`); return; }\n  throw e;\n}","preventionTips":["Design batch downloads to skip-and-log per track","Read the embedded reason text: region vs copyright vs removed need different handling","Don't retry UNPLAYABLE tracks — the state is stable, not transient"],"tags":["downloader","youtube","unplayable","geo-restriction","content-unavailable"],"backgroundTag":"content-unavailable","analyzedSha":"1e2aac5706c870c93ed74ba8727ae8390d3b0fa5","analyzedAt":"2026-08-27T20:01:08.614Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}