tonhowtf/omniget · error · anyhow::Error

isso é um vídeo, não um perfil

Error message

isso é um vídeo, não um perfil: {}

What it means

After parse_target succeeds, expand_profile matches on the Target variant; anything that is not User/Collection/Music (i.e. a single video target) is rejected with "isso é um vídeo, não um perfil: {input}" (this is a video, not a profile). It enforces that profile expansion only handles list-like targets.

Solutions

  1. Put video URLs in opts.urls instead of opts.profile
  2. Use a profile/collection/music URL for profile expansion
  3. Detect the target type with parse_target in caller code and route videos to the single-video path

Example fix

// before
run(&Options { profile: Some("https://www.tiktok.com/@u/video/123".into()), .. })
// after
run(&Options { urls: vec!["https://www.tiktok.com/@u/video/123".into()], .. })
Defensive patterns

Strategy: type-guard

Validate before calling

let is_video = input.contains("/video/");
if is_video { /* route to single-video download via opts.urls */ }

Type guard

fn is_video_url(input: &str) -> bool {
    input.contains("/video/") || input.contains("/photo/")
}

Try / catch

match run(&opts, progress).await {
    Err(e) if e.to_string().contains("isso é um vídeo") => {
        // move the URL from opts.profile to opts.urls and retry as video
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling run with opts.profile set to a URL that parses as a single TikTok video (e.g. https://www.tiktok.com/@user/video/123...), so the match falls through to the error arm.

Common situations: Copying a video URL into the profile field of the UI/CLI; automation filling the wrong option (profile vs url); a URL shape that parse_target classifies as Video rather than User.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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

Appendix: source

Thrown at src-tauri/omniget-core/src/core/tools/tiktok/download.rs:127

        }
    }
    if limit > 0 && out.len() > limit as usize {
        out.truncate(limit as usize);
    }
    out
}

/// Lista os vídeos de um perfil ou coleção com uma só chamada de yt-dlp.
async fn expand_profile(
    input: &str,
    limit: u32,
    cookies: Option<&std::path::Path>,
) -> Result<Vec<String>> {
    let target = parse_target(input)
        .ok_or_else(|| anyhow!("não reconheci esse perfil ou coleção: {}", input))?;
    match target {
        Target::User { .. } | Target::Collection { .. } | Target::Music { .. } => {}
        _ => return Err(anyhow!("isso é um vídeo, não um perfil: {}", input)),
    }
    let url = canonical_url(&target);
    let v = super::ytdlp_json(&super::ytdlp_list_args(&url, limit, cookies)).await?;
    let entries = super::favorites::entries_from_list(&v);
    Ok(entries.into_iter().map(|e| e.url).collect())
}

fn cookies_path(opts: &Options, session: &TempCookies) -> Option<PathBuf> {
    if let Some(c) = opts.cookies.as_deref().filter(|c| !c.trim().is_empty()) {
        return Some(PathBuf::from(c));
    }
    session.path().map(|p| p.to_path_buf())
}

pub async fn run(opts: &Options, progress: ProgressFn) -> Result<DownloadResult> {
    let dest = PathBuf::from(&opts.dest);
    if opts.dest.trim().is_empty() {
        return Err(anyhow!("escolha a pasta de destino"));

View on GitHub (pinned to 8600b91f42)