tonhowtf/omniget · info · Error
empty stream url
Error message
empty stream url
What it means
Raised by extract_graphql_media when the tweet result uses the "Tweet" or "TweetWithVisibilityResults" typename but Self::media_arrays_from_tweet_result returns None — the tweet parsed successfully yet contains no recognizable media arrays (extended_entities/entities/media or similar).
Solutions
- Verify the tweet actually contains media before calling the extractor (or accept this as a normal skip result)
- Check for a recent Twitter GraphQL schema change and update media_arrays_from_tweet_result field paths
- Log the raw tweet_result JSON on failure to confirm which field names are present
- Use a pinned, known-good GraphQL operation ID/query hash in case the endpoint changed
Example fix
// before
let media = Self::media_arrays_from_tweet_result(tweet_result)
.ok_or_else(|| anyhow!("No media found in tweet"))?;
// after
match Self::media_arrays_from_tweet_result(tweet_result) {
Some(media) if !media.is_empty() => Ok(media),
_ => Err(TwitterError::NoMedia { tweet_id }), // lets callers distinguish text-only tweets from schema breakage
} Defensive patterns
Strategy: validation
Validate before calling
// Check the tweet has media before invoking media extraction
if (!tweet?.extended_entities?.media?.length && !tweet?.entities?.media?.length) {
return skip(id, 'text-only tweet');
} Type guard
function hasExtractableMedia(tweetResult) {
return Array.isArray(tweetResult?.legacy?.extended_entities?.media) &&
tweetResult.legacy.extended_entities.media.length > 0;
} Try / catch
match tweet.extract_graphql_media(id) {
Err(e) if e.to_string() == "No media found in tweet" => skip(id, Reason::TextOnly),
other => other,
} Prevention
- Filter input URLs/tweet_ids to media-bearing posts when possible
- Watch for spikes of this error — they indicate a Twitter GraphQL schema change, not bad data
- Pin and periodically verify the GraphQL query hash/operation ID
- Log the raw tweet_result JSON when extraction fails to see actual field names
When it happens
Trigger: Calling extract_graphql_media on a text-only tweet (no photos/videos/GIFs), or on a tweet whose media fields were stripped/renamed by a Twitter GraphQL schema change so media_arrays_from_tweet_result can no longer find them.
Common situations: Queuing arbitrary tweet URLs without checking they contain media; the account posted a poll/text-only reply; Twitter shipped a GraphQL schema change renaming entities fields, breaking extraction for ALL tweets until the parser is updated.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- No downloadable media found for this tweet (it may be…
- No media found in tweet
- No photo URLs found in HTML
- ERR_TOO_MANY_ATTACHMENTS
- HLS nao e suportado neste navegador
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/b88c484422e9d939.
Report an issue: GitHub.
Appendix: source
Thrown at src/lib/study-music/player-store.svelte.ts:1565
if (!this.audio) return;
const videoId = track.youtube_video_id;
if (!videoId) {
this.setError(
classifyPlayerError("video id ausente — track removed", "youtube", track.id),
);
return;
}
this.loading = true;
await this.stopCurrentPlayback();
this.youtubeCurrentVideoId = videoId;
this.youtubeVideoUrl = null;
this.youtubeChapters = [];
this.youtubeSponsorBlockSegments = [];
this.youtubeRefreshFailureCount = 0;
try {
const { audio: audioUrl, video: videoUrl } =
await this.resolveYoutubeMedia(videoId);
if (!audioUrl) throw new Error("empty stream url");
this.audio.crossOrigin = null;
this.audio.src = audioUrl;
this.youtubeVideoUrl = videoUrl;
void this.refreshYoutubeSponsorBlock(videoId);
await this.audio.play();
this.saveQueueNow();
this.updateMediaSessionMetadata(track);
void this.refreshDominantColor(track);
void pluginInvoke("study", "study:music:youtube:track_record_play", {
video_id: videoId,
}).catch(() => {});
} catch (e) {
this.setError(classifyPlayerError(e, "youtube", track.id));
}
}
private cancelYoutubeRefresh() {
if (this.youtubeRefreshTimer) {View on GitHub (pinned to 8600b91f42)