{"record":{"id":"bdba07471af2a187","repo":"tonhowtf/omniget","slug":"refresh-returned-no-audio-format","errorCode":null,"errorMessage":"refresh returned no audio format","messagePattern":"refresh returned no audio format","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/lib/study-music/player-store.svelte.ts","lineNumber":1645,"sourceCode":"    this.cancelYoutubeRefresh();\n    const now = Math.floor(Date.now() / 1000);\n    const delaySecs = Math.max(30, expiresAt - now - 60);\n    this.youtubeRefreshTimer = setTimeout(() => {\n      void this.refreshYoutubeStream(videoId);\n    }, delaySecs * 1000);\n  }\n\n  private async refreshYoutubeStream(videoId: string) {\n    if (!this.audio) return;\n    if (this.youtubeCurrentVideoId !== videoId) return;\n    if (this.currentTrack?.youtube_video_id !== videoId) return;\n    try {\n      const { studyYoutubePlayer } = await import(\"$lib/study-bridge\");\n      console.info(\"[study-music] yt refresh start\", { videoId });\n      const res = await studyYoutubePlayer({ videoId });\n      const url = pickBestYoutubeAudio(res);\n      const videoUrl = pickBestYoutubeVideo(res);\n      if (!url) throw new Error(\"refresh returned no audio format\");\n      const wasPaused = this.audio.paused;\n      const t = this.audio.currentTime;\n      this.audio.crossOrigin = null;\n      this.audio.src = url;\n      this.audio.currentTime = t;\n      this.youtubeVideoUrl = videoUrl;\n      if (!wasPaused) await this.audio.play();\n      this.youtubeChapters = res.chapters ?? this.youtubeChapters;\n      this.youtubeRefreshFailureCount = 0;\n      this.scheduleYoutubeRefresh(videoId, res.expires_at);\n      console.info(\"[study-music] yt refresh ok\", { videoId, expires_at: res.expires_at });\n    } catch (err) {\n      this.youtubeRefreshFailureCount += 1;\n      console.warn(\n        \"[study-music] yt refresh failed\",\n        { videoId, attempt: this.youtubeRefreshFailureCount },\n        err,\n      );","sourceCodeStart":1627,"sourceCodeEnd":1663,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src/lib/study-music/player-store.svelte.ts#L1627-L1663","documentation":"The catch-all arm of the __typename match in extract_graphql_media. Any GraphQL tweet result whose __typename is not one of the handled variants (tombstone types, \"Tweet\", \"TweetWithVisibilityResults\") produces this generic \"Post not available\" error, meaning the response shape is unknown to the extractor.","triggerScenarios":"extract_graphql_media receives a tweet_result whose __typename is an unhandled value (e.g. a new Twitter entity type, a profile/redirection variant, or a missing __typename resolving to the wildcard arm).","commonSituations":"Twitter introduces a new __typename in its GraphQL responses; the extractor is fed the wrong JSON node (e.g. the outer tweet container instead of the inner result); API experiments rolling out new card/embed types to a fraction of responses.","solutions":["Log the unhandled __typename value and add an explicit match arm for it","Update the GraphQL query hash/operation ID to a version with known response shapes","Verify you are passing tweet_result (the inner result object) rather than the outer wrapper node","Check the library's repo/issues for reports of new Twitter __typename values"],"exampleFix":"// before\n_ => Err(anyhow!(\"Post not available\")),\n// after\nother => {\n    tracing::warn!(\"[twitter] unhandled typename={:?} tweet_id={}\", other, tweet_id);\n    Err(anyhow!(\"Post not available: unhandled typename {:?}\", other))\n}","handlingStrategy":"try-catch","validationCode":"// Narrow the response shape before extraction\nconst t = result?.data?.tweetResult?.result;\nif (!t || !['__typename' in t].every(Boolean)) throw new MalformedResponseError(id);","typeGuard":"function isKnownTypename(result) {\n  return ['TweetTombstone','TweetUnavailable','Tweet','TweetWithVisibilityResults']\n    .includes(result?.__typename);\n}","tryCatchPattern":"match tweet.extract_graphql_media(id) {\n    Err(e) if e.to_string() == \"Post not available\" => {\n        tracing::warn!(\"unhandled tweet shape, tweet_id={}\", id);\n        mark_unavailable(id);\n    }\n    other => other,\n}","preventionTips":["Always log the raw __typename when hitting the wildcard arm","Keep the GraphQL operation pinned to a known response schema","Alert on any rise in this error — it usually means Twitter added a new __typename","Add exhaustive match arms with typed error messages instead of a bare wildcard"],"tags":["twitter","graphql","unexpected-response-shape","unhandled-case"],"backgroundTag":"unexpected-response-shape","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}