{"record":{"id":"e75c630f363dce62","repo":"tonhowtf/omniget","slug":"study-music-study-youtube-player-failed-falling-back-to-yt","errorCode":null,"errorMessage":"[study-music] study:youtube:player failed, falling back to yt-dlp resolver:","messagePattern":"\\[study-music\\] study:youtube:player failed, falling back to yt-dlp resolver:","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/lib/study-music/player-store.svelte.ts","lineNumber":1607,"sourceCode":"  private async resolveYoutubeMedia(\n    videoId: string,\n  ): Promise<{ audio: string | null; video: string | null; legacy: boolean }> {\n    try {\n      const { studyYoutubePlayer } = await import(\"$lib/study-bridge\");\n      const res = await studyYoutubePlayer({ videoId });\n      if (res.sabr_only) {\n        throw new Error(\n          \"SABR-only stream: no directly playable format (format unavailable in this client yet)\",\n        );\n      }\n      const audio = pickBestYoutubeAudio(res);\n      const video = pickBestYoutubeVideo(res);\n      if (!audio) throw new Error(\"no audio format returned\");\n      this.youtubeChapters = res.chapters ?? [];\n      this.scheduleYoutubeRefresh(videoId, res.expires_at);\n      return { audio, video, legacy: false };\n    } catch (err) {\n      console.warn(\n        \"[study-music] study:youtube:player failed, falling back to yt-dlp resolver:\",\n        err,\n      );\n      const legacy = await pluginInvoke<{ url: string; via?: string }>(\n        \"study\",\n        \"study:music:youtube:track_stream_url\",\n        { video_id: videoId },\n      );\n      if (!legacy.url) {\n        throw err instanceof Error\n          ? err\n          : new Error(typeof err === \"string\" ? err : \"youtube resolve failed\");\n      }\n      this.youtubeChapters = [];\n      return { audio: legacy.url, video: null, legacy: true };\n    }\n  }\n","sourceCodeStart":1589,"sourceCodeEnd":1625,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src/lib/study-music/player-store.svelte.ts#L1589-L1625","documentation":"The player's preferred YouTube pipeline (study:youtube:player, returning audio+video formats and chapters) failed, and the store deliberately falls back to the legacy yt-dlp resolver (study:music:youtube:track_stream_url). This warn is the diagnostic breadcrumb for that fallback path, not a playback failure — playback continues via the legacy resolver.","triggerScenarios":"pluginInvoke('study','study:youtube:player',{videoId}) rejecting or returning no audio format ('no audio format returned') while resolving a YouTube track; then the legacy track_stream_url call is attempted.","commonSituations":"Backend resolver can't find a suitable audio itag; YouTube throttles or blocks the primary API; expiry/degradation of the player endpoint; age/region-restricted videos returning empty format lists; backend yt-dlp-only build lacking the primary player command.","solutions":["Read the logged `err` to see whether it's a command failure or 'no audio format returned'.","Retry the primary command once — transient YouTube API failures are common.","Confirm the backend's yt-dlp is up to date, since the legacy path is the only one that works when the primary fails.","If primary failures are persistent, check backend network egress/YouTube client config for the study:youtube:player resolver."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// pre-check resolver availability\nconst hasPlayer = await pluginInvoke<boolean>(\"study\", \"study:music:has_youtube_player\").catch(() => false);","typeGuard":"function hasAudioFormat(res: unknown): res is { audio: { url: string }; video?: unknown; chapters?: unknown[] } {\n  return typeof res === \"object\" && res !== null && \"audio\" in res;\n}","tryCatchPattern":"try {\n  const res = await pluginInvoke(\"study\", \"study:youtube:player\", { videoId });\n  if (!res?.audio) throw new Error(\"no audio format returned\");\n} catch (err) {\n  console.warn(\"[study-music] primary resolver failed, falling back:\", err);\n  const legacy = await pluginInvoke(\"study\", \"study:music:youtube:track_stream_url\", { videoId });\n}","preventionTips":["Keep yt-dlp updated in the backend since it's the fallback path.","Add a single retry for the primary resolver before falling back.","Log which resolver served each track for easier triage.","Monitor fallback frequency as a health signal for the primary pipeline."],"tags":["youtube","fallback","network","streaming"],"backgroundTag":"fallback-resolver-engaged","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}