{"record":{"id":"b04e64eee358b89c","repo":"tonhowtf/omniget","slug":"unsupported-link","errorCode":null,"errorMessage":"Unsupported link","messagePattern":"Unsupported link","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/platforms/bluesky.rs","lineNumber":147,"sourceCode":"        let uri = format!(\"at://{}/app.bsky.feed.post/{}\", user, post_id);\n        let url = format!(\n            \"{}?depth=0&parentHeight=0&uri={}\",\n            API_BASE,\n            urlencoding::encode(&uri)\n        );\n\n        let response = self.client.get(&url).send().await?;\n\n        if !response.status().is_success() {\n            return Err(anyhow!(\"Bluesky API retornou HTTP {}\", response.status()));\n        }\n\n        let json: serde_json::Value = response.json().await?;\n\n        if let Some(error) = json.get(\"error\").and_then(|e| e.as_str()) {\n            return match error {\n                \"NotFound\" | \"InternalServerError\" => Err(anyhow!(\"Post not available\")),\n                \"InvalidRequest\" => Err(anyhow!(\"Unsupported link\")),\n                _ => Err(anyhow!(\"Erro da API: {}\", error)),\n            };\n        }\n\n        Ok(json)\n    }\n}\n\nenum BlueskyMedia {\n    Video { hls_url: String },\n    Images { urls: Vec<String> },\n    Gif { url: String },\n}\n\nfn extract_media(embed: &serde_json::Value) -> Option<BlueskyMedia> {\n    let embed_type = embed.get(\"$type\")?.as_str()?;\n\n    match embed_type {","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/platforms/bluesky.rs#L129-L165","documentation":"Thrown in fetch_post when the Bluesky API returns error \"InvalidRequest\". The getPostThread call was rejected as malformed — typically the at:// URI (handle/post id) built from the input URL is invalid, so the link itself is not a usable Bluesky post.","triggerScenarios":"The input URL parses as bsky.app but extract_user_and_post yields a handle or post id that doesn't form a valid at:// URI (e.g. custom domain handles, unusual path segments, or a non-post bsky.app link that passed can_handle).","commonSituations":"Links like bsky.app/profile/<did>/post/<id> with unexpected characters, shortened/altered URLs, or non-post bsky.app pages (profile pages, starter packs) reaching the downloader.","solutions":["Validate the post id looks like a valid atproto TID (13-char base32-ish string) before calling the API.","Ensure the URL is a direct post link, not a profile or other bsky.app page.","Resolve handle-to-DID properly if the API rejects handle-based at:// URIs.","Show an 'unsupported link' message and reject the URL early in can_handle/parsing."],"exampleFix":"// before\nfn extract_user_and_post(url: &str) -> Option<(String, String)> {\n    ...\n}\n// after: reject obviously malformed post ids early\nif post_id.len() != 13 || !post_id.chars().all(|c| c.is_ascii_alphanumeric()) {\n    return None; // caller emits \"Could not extract user and post_id\"\n}","handlingStrategy":"validation","validationCode":"let parsed = url::Url::parse(url)?;\nlet segs: Vec<&str> = parsed.path().split('/').filter(|s| !s.is_empty()).collect();\nlet ok = segs.len() >= 4 && segs[0] == \"profile\" && segs[2] == \"post\"\n    && segs[3].len() == 13 && segs[3].chars().all(|c| c.is_ascii_alphanumeric());\nif !ok { return Err(anyhow!(\"not a valid bsky post link\")); }","typeGuard":"fn is_bsky_post_url(url: &str) -> bool {\n    url::Url::parse(url).ok()\n        .filter(|u| u.host_str().map_or(false, |h| h == \"bsky.app\" || h.ends_with(\".bsky.app\")))\n        .and_then(|u| {\n            let s: Vec<&str> = u.path().split('/').filter(|x| !x.is_empty()).collect();\n            if s.len() >= 4 && s[0] == \"profile\" && s[2] == \"post\" { Some((s[1], s[3])) } else { None }\n        })\n        .map_or(false, |(_, id)| id.len() == 13 && id.chars().all(|c| c.is_ascii_alphanumeric()))\n}","tryCatchPattern":"if !is_bsky_post_url(url) {\n    return Err(anyhow!(\"unsupported link: expected bsky.app/profile/<user>/post/<id>\"));\n}\nlet info = downloader.get_media_info(url).await?;","preventionTips":["Only accept canonical bsky.app/<handle>/post/<id> links","Reject profile pages and other bsky.app routes before calling the downloader","Beware URL shorteners or copied links with trailing path fragments"],"tags":["bluesky","invalid-url","api"],"backgroundTag":"invalid-url-format","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"}