tonhowtf/omniget · error

Could not resolve short link

Error message

Could not resolve short link

What it means

resolve_short_link in tiktok.rs follows TikTok short links (vm.tiktok.com / vt.tiktok.com) by fetching the page and scraping the canonical/redirect URL out of the HTML. If none of the extraction patterns match the response, it returns this error, meaning the short link could not be expanded to a full video URL.

Solutions

  1. Prefer following HTTP redirects (reqwest redirect policy) instead of scraping HTML for the URL
  2. Log the fetched HTML when this fires and add the new URL pattern to the extraction logic
  3. Retry — short-link resolution can transiently return interstitial pages
  4. Fall back to constructing the canonical /video/{id} URL from the ID in the short link

Example fix

// before
Err(anyhow!("Could not resolve short link"))
// after
Err(anyhow!("Could not resolve short link: {} (page layout may have changed)", short_url))
Defensive patterns

Strategy: fallback

Validate before calling

if (/^https:\/\/(vm|vt)\.tiktok\.com\//.test(url)) {
  // short link: be prepared to fall back if expansion fails
}

Try / catch

let canonical = match tiktok.resolve_short_link(short).await {
    Ok(u) => u,
    Err(_) => follow_http_redirects(short).await?, // fallback
};

Prevention

When it happens

Trigger: get_media_info calls resolve_short_link with a vm./vt.tiktok.com URL and: the HTML layout no longer contains the expected anchor/JSON URL markers, TikTok serves a redirect page variant, or an interstitial (captcha/region) page is returned instead.

Common situations: TikTok changing the short-link redirect page markup; a new URL field format that split('"')/split('?') logic misses; regional redirects serving different HTML; heavy bot protection returning blank pages.

Related errors


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

Appendix: source

Thrown at src-tauri/omniget-core/src/platforms/tiktok.rs:111

            .headers()
            .get("location")
            .and_then(|v| v.to_str().ok())
        {
            let clean = location.split('?').next().unwrap_or(location).to_string();
            return Ok(clean);
        }

        let html = response.text().await?;

        if html.starts_with("<a href=\"https://") {
            if let Some(url_part) = html.split("<a href=\"").nth(1) {
                let full_url = url_part.split('"').next().unwrap_or(url_part);
                let clean = full_url.split('?').next().unwrap_or(full_url).to_string();
                return Ok(clean);
            }
        }

        Err(anyhow!("Could not resolve short link"))
    }

    fn is_captcha_page(html: &str) -> bool {
        html.contains("verify-bar-close")
            || html.contains("captcha_verify")
            || html.contains("tiktok-verify-page")
            || html.contains("verify/page")
            || (html.contains("Verify to continue")
                && !html.contains("__UNIVERSAL_DATA_FOR_REHYDRATION__"))
    }

    fn is_valid_play_addr(url: &str) -> bool {
        if url.is_empty() {
            return false;
        }
        if !url.starts_with("http://") && !url.starts_with("https://") {
            return false;
        }

View on GitHub (pinned to 8600b91f42)