tonhowtf/omniget · error

Could not extract tweet ID

Error message

Could not extract tweet ID

What it means

native_get_media_info calls Self::extract_tweet_id(url), which parses the tweet ID out of the URL; it returns Option and this error is raised (via ok_or_else) when the result is None. It means the URL was accepted by can_handle (a twitter.com/x.com/vxtwitter.com/fixvx.com host) but its path does not contain a recognizable numeric tweet ID.

Solutions

  1. Ensure the URL contains /status/<numeric-id> (e.g. https://x.com/<user>/status/1234567890123456789).
  2. Resolve any shortener/redirect links to the final x.com or twitter.com URL before calling get_media_info.
  3. Validate the URL with a regex like /status/(\d+) before invoking the downloader to give users a clearer message.
  4. If the URL uses vxtwitter/fixvx rewriting, confirm the path still preserves the status/ID segment.
  5. Update extract_tweet_id if Twitter introduced a new valid URL format it no longer matches.

Example fix

// before
let url = "https://x.com/someuser"; // no status path
downloader.get_media_info(url).await?;
// after
let re = regex::Regex::new(r"/status/(\d+)").unwrap();
if !re.is_match(&url) {
    anyhow::bail!("not a tweet permalink: {}", url);
}
let info = downloader.get_media_info(url).await?;
Defensive patterns

Strategy: validation

Validate before calling

static TWEET_ID_RE: once_cell::sync::Lazy<regex::Regex> =
    once_cell::sync::Lazy::new(|| regex::Regex::new(r"/status/(\d+)").unwrap());

fn is_tweet_permalink(url: &str) -> bool {
    TWEET_ID_RE.is_match(url)
}
// call is_tweet_permalink(url) before get_media_info

Type guard

fn is_tweet_permalink(url: &str) -> bool {
    regex::Regex::new(r"https?://(www\.)?(x|twitter|vxtwitter|fixvx)\.com/\S+/status/\d+")
        .map(|re| re.is_match(url))
        .unwrap_or(false)
}

Try / catch

match downloader.get_media_info(url).await {
    Err(e) if e.to_string().contains("Could not extract tweet ID") => {
        eprintln!("'{url}' is not a tweet permalink; expected x.com/<user>/status/<id>");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling get_media_info with a Twitter-domain URL that has no /status/<digits> segment — e.g. profile URLs (https://x.com/user), status with non-numeric or truncated ID, URLs like https://x.com/user/status (missing ID), localized/redirect paths, or alternate front-end hosts (vxtwitter/fixvx) with rewritten paths.

Common situations: Users pasting profile or home-timeline links instead of a tweet link; URL shortener output that hasn't been resolved; malformed copy-paste that truncates the ID; code feeding can_handle-approved URLs without validating the status path; regex in extract_tweet_id lagging behind new URL shapes.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12). Data as JSON: /api/errors/4763bc30e09359c2. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/omniget-core/src/platforms/twitter.rs:900

    async fn fallback_ytdlp(&self, url: &str) -> anyhow::Result<MediaInfo> {
        let ytdlp_path = crate::core::ytdlp::ensure_ytdlp().await?;
        let mut extra_flags = vec![
            "--referer".to_string(),
            "https://x.com/".to_string(),
            "--add-headers".to_string(),
            "Referer:https://x.com/".to_string(),
        ];
        if let Some(cookie) = Self::auth_cookie_string() {
            extra_flags.push("--add-headers".to_string());
            extra_flags.push(format!("Cookie:{}", cookie));
        }
        let json = crate::core::ytdlp::get_video_info(&ytdlp_path, url, &extra_flags).await?;
        crate::platforms::generic_ytdlp::GenericYtdlpDownloader::parse_video_info(&json)
    }

    async fn native_get_media_info(&self, url: &str) -> anyhow::Result<MediaInfo> {
        let tweet_id =
            Self::extract_tweet_id(url).ok_or_else(|| anyhow!("Could not extract tweet ID"))?;
        tracing::debug!(
            "[twitter] native_get_media_info tweet_id={} url={}",
            tweet_id,
            url
        );

        let filename_base = format!("twitter_{}", tweet_id);

        let media_items = match self.try_graphql(&tweet_id).await {
            Ok(items) => items,
            Err(graphql_err) => {
                tracing::warn!(
                    "[twitter] graphql lookup failed for tweet_id={}: {}",
                    tweet_id,
                    graphql_err
                );
                match self.request_syndication(&tweet_id).await {
                    Ok(syndication) => match Self::extract_syndication_media(&syndication) {

View on GitHub (pinned to 8600b91f42)