tonhowtf/omniget · error
Post does not contain media
Error message
Post does not contain media
What it means
After fetching the post JSON, native_get_media_info() reads the JSON pointer /thread/post/embed. If the pointer is absent the post has no embedded media (plain text post, or embed in an unexpected place) and this error is returned. It distinguishes a successfully fetched but non-media post from a network/parsing failure.
Solutions
- Confirm the post actually contains an image or video (not text-only).
- Handle record_with_media: also check thread.post.embed.record.embed / embeds array for nested media.
- Return a clearer message distinguishing text-only posts from unsupported embed types.
- Verify against the current AppView schema if Bluesky changed embed nesting.
Example fix
// before
let embed = json.pointer("/thread/post/embed").ok_or_else(|| anyhow!("Post does not contain media"))?;
// after
let embed = json.pointer("/thread/post/embed")
.or_else(|| json.pointer("/thread/post/embed/record/embed"))
.or_else(|| json.pointer("/thread/post/embeds/0"))
.ok_or_else(|| anyhow!("Post does not contain media (text-only or unsupported embed type)"))?; Defensive patterns
Strategy: try-catch
Type guard
fn embed_of(post_json: &serde_json::Value) -> Option<&serde_json::Value> {
post_json.pointer("/thread/post/embed")
.or_else(|| post_json.pointer("/thread/post/embed/record/embed"))
.or_else(|| post_json.pointer("/thread/post/embeds/0"))
} Try / catch
match get_media_info(url).await {
Err(e) if e.to_string().contains("Post does not contain media") => {
eprintln!("this post is text-only or uses an unsupported embed type");
Err(e)
}
other => other,
} Prevention
- Only pass posts known to contain images or video.
- Handle reposts and record_with_media via nested JSON pointers.
- Check for an 'embeds' array fallback since Bluesky supports multiple embed forms.
- Re-validate pointer paths after Bluesky AppView schema updates.
When it happens
Trigger: get_media_info() -> native_get_media_info() where fetch_post() succeeds but the returned AppView JSON has no thread.post.embed object — i.e. a text-only post, a repost, a deleted embed, or an embed-variant (e.g. record_with_media) at a different JSON path.
Common situations: User passes a text-only skeet URL; post is a repost of media living under a different pointer; Bluesky AppView changed the embed shape (recordWithMedia nesting) so the fixed pointer misses.
Related errors
- Unsupported media type
- release de sem assets
- a saída do gallery-dl não é um dump JSON válido
- No URL available
- No URL available
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/539b48b8f4d8c65c.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/omniget-core/src/platforms/bluesky.rs:39
}
}
impl BlueskyDownloader {
async fn fallback_ytdlp(&self, url: &str) -> anyhow::Result<MediaInfo> {
let ytdlp_path = crate::core::ytdlp::ensure_ytdlp().await?;
let json = crate::core::ytdlp::get_video_info(&ytdlp_path, url, &[]).await?;
crate::platforms::generic_ytdlp::GenericYtdlpDownloader::parse_video_info(&json)
}
async fn native_get_media_info(&self, url: &str) -> anyhow::Result<MediaInfo> {
let (user, post_id) = Self::extract_user_and_post(url)
.ok_or_else(|| anyhow!("Could not extract user and post_id from URL"))?;
let json = self.fetch_post(&user, &post_id).await?;
let embed = json
.pointer("/thread/post/embed")
.ok_or_else(|| anyhow!("Post does not contain media"))?;
let media = extract_media(embed).ok_or_else(|| anyhow!("Unsupported media type"))?;
let filename_base = format!("bluesky_{}_{}", sanitize_filename::sanitize(&user), post_id);
match media {
BlueskyMedia::Video { hls_url } => Ok(MediaInfo {
title: filename_base,
author: user,
platform: "bluesky".to_string(),
duration_seconds: None,
thumbnail_url: None,
available_qualities: vec![VideoQuality {
label: "best".to_string(),
width: 0,
height: 0,
url: hls_url,
format: "hls".to_string(),View on GitHub (pinned to 8600b91f42)