{"record":{"id":"46509495f1012200","repo":"tonhowtf/omniget","slug":"could-not-extract-post-id-mod","errorCode":null,"errorMessage":"Could not extract post ID","messagePattern":"Could not extract post ID","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-tauri/src/platforms/instagram/mod.rs","lineNumber":675,"sourceCode":"                return host == \"instagram.com\"\n                    || host.ends_with(\".instagram.com\")\n                    || host == \"ddinstagram.com\"\n                    || host.ends_with(\".ddinstagram.com\");\n            }\n        }\n        false\n    }\n\n    async fn get_media_info(&self, url: &str) -> anyhow::Result<MediaInfo> {\n        if Self::is_story_url(url) {\n            return Err(anyhow!(\n                \"Instagram Stories are not supported. Only public posts, reels and carousels.\"\n            ));\n        }\n\n        let post_id = if let Some(share_id) = Self::extract_share_id(url) {\n            let resolved = self.resolve_share_link(&share_id).await?;\n            Self::extract_post_id(&resolved).ok_or_else(|| anyhow!(\"Could not extract post ID\"))?\n        } else {\n            Self::extract_post_id(url).ok_or_else(|| anyhow!(\"Could not extract post ID\"))?\n        };\n\n        let filename_base = format!(\"instagram_{}\", post_id);\n\n        let embed_result = self.request_embed(&post_id).await;\n        let media = match embed_result {\n            Ok(data) => Self::extract_media_from_embed(&data),\n            Err(_embed_err) => match self.request_gql(&post_id).await {\n                Ok(data) => Self::extract_media_from_gql(&data),\n                Err(_gql_err) => {\n                    return self.fallback_ytdlp(url, &post_id).await;\n                }\n            },\n        };\n\n        let media = match media {","sourceCodeStart":657,"sourceCodeEnd":693,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/src/platforms/instagram/mod.rs#L657-L693","documentation":"Raised in `get_media_info` when `extract_post_id` returns None for the URL resolved from a share link. `extract_post_id` only matches path shapes `/p/<id>`, `/reel/<id>`, `/reels/<id>`, `/tv/<id>`; any other resolved URL shape has no extractable post ID, so the flow aborts.","triggerScenarios":"Calling `get_media_info` with a `/share/<id>` link whose redirect lands on a URL that does not match the supported post path patterns — e.g. redirect to a profile page, login page, or a new Instagram path scheme.","commonSituations":"Share links redirecting to `/stories/` or `/explore/` pages; expired share links bouncing to the login wall; Instagram introducing a new canonical path segment the parser doesn't know; malformed URLs that parse but have no media segment.","solutions":["Log the resolved URL (`resolve_share_link` output) and check what path shape it actually redirects to","Ensure the share link resolves to /p/, /reel/, /reels/ or /tv/ before calling; otherwise surface an 'unsupported URL' message to the user","Extend `extract_post_id`'s match arms if Instagram added a new canonical path prefix","Handle the 'Could not resolve share link' error upstream so dead share links never reach ID extraction"],"exampleFix":"// before\nlet post_id = Self::extract_post_id(&resolved)\n    .ok_or_else(|| anyhow!(\"Could not extract post ID\"))?;\n// after\nlet post_id = Self::extract_post_id(&resolved).ok_or_else(|| {\n    anyhow!(\"Could not extract post ID from resolved URL: {resolved}\")\n})?;","handlingStrategy":"validation","validationCode":"fn looks_like_post_url(url: &str) -> bool {\n    url::Url::parse(url).ok()\n        .map(|u| {\n            let segs: Vec<&str> = u.path().split('/').filter(|s| !s.is_empty()).collect();\n            matches!(segs.first(), Some(&\"p\") | Some(&\"reel\") | Some(&\"reels\") | Some(&\"tv\"))\n                && segs.get(1).map_or(false, |s| !s.is_empty())\n        })\n        .unwrap_or(false)\n}","typeGuard":"fn extract_post_id_guard(url: &str) -> Option<String> {\n    let parsed = url::Url::parse(url).ok()?;\n    let segs: Vec<&str> = parsed.path().split('/').filter(|s| !s.is_empty()).collect();\n    match segs.first() {\n        Some(&\"p\") | Some(&\"reel\") | Some(&\"reels\") | Some(&\"tv\") => segs.get(1).map(|s| s.to_string()),\n        _ => None,\n    }\n}","tryCatchPattern":"match downloader.get_media_info(&share_url).await {\n    Err(e) if e.to_string().contains(\"Could not extract post ID\") => {\n        tracing::warn!(\"share link resolved to unsupported path; ask user for canonical post URL\");\n        Err(anyhow!(\"Share link did not point to a post/reel; paste the direct /p/ or /reel/ URL\"))\n    }\n    other => other,\n}","preventionTips":["Log the final URL returned by resolve_share_link to diagnose unexpected redirect targets","Treat expired share links as user-input errors and prompt for the canonical URL","Keep extract_post_id's accepted path patterns in sync with Instagram's current URL scheme","Test share-link resolution against live short links regularly; Instagram redirect targets change"],"tags":["instagram","url-parsing","share-link"],"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"}