tonhowtf/omniget · error

vimeo:{code}

vimeo:{code}

Error message

vimeo:{code}

What it means

Compact error form thrown by run_json when yt-dlp exits non-zero and its stderr tail matches a known error_code pattern (vimeo.rs:761). Instead of leaking the full stderr, the library normalizes it to `vimeo:<code>` (e.g., login-required, private video, geo-restriction) so callers can match programmatically. Secrets are scrubbed from the message before classification.

Solutions

  1. Parse the code after the `vimeo:` prefix and map it to a user-facing message (private, geo-blocked, etc.).
  2. For login-required codes, supply cookies/credentials (`--cookies-from-browser` or the app's auth option).
  3. For geo/removed content, there is no retry fix — inform the user the video is unavailable.
  4. For rate-limit codes, back off and retry later with reduced concurrency (acquire_ytdlp_slot already throttles).
Defensive patterns

Strategy: type-guard

Validate before calling

fn vimeo_code(err: &anyhow::Error) -> Option<&str> {
    let s = err.to_string();
    s.strip_prefix("vimeo:").map(|c| c.trim())
}

Type guard

fn is_vimeo_coded_error(msg: &str) -> Option<&str> {
    msg.strip_prefix("vimeo:").filter(|c| !c.is_empty())
}

Try / catch

match one(url).await {
    Err(e) => match is_vimeo_coded_error(&e.to_string()) {
        Some("login-required" | "private") => eprintln!("vídeo privado: forneça cookies de autenticação"),
        Some("geo-restricted") => eprintln!("vídeo indisponível na sua região"),
        Some(code) => eprintln!("vimeo falhou: {code}"),
        None => return Err(e),
    },
    ok => ok,
}

Prevention

When it happens

Trigger: Any Vimeo enumeration via run_json where yt-dlp fails with a recognized condition: video is private or members-only, login/cookies required, geo-blocked, removed, or rate-limited — error_code() matches the stderr tail.

Common situations: Attempting to list a private showcase without cookies; Vimeo DRM/member-only content; region-locked videos; Vimeo throttling an IP after heavy enumeration.

Related errors


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

Appendix: source

Thrown at src-tauri/omniget-core/src/core/tools/vimeo.rs:761

/// Roda o yt-dlp e devolve o stdout inteiro. Usado só pela enumeração.
async fn run_json(bin: &Path, args: &[String], secrets: &[&str]) -> Result<String> {
    let _slot = crate::core::ytdlp::acquire_ytdlp_slot("vimeo-list").await;
    let mut cmd = crate::core::ytdlp::ytdlp_command(bin);
    cmd.args(args).stdin(std::process::Stdio::null());
    let out = cmd
        .output()
        .await
        .map_err(|e| anyhow!("não foi possível iniciar o yt-dlp: {e}"))?;
    if !out.status.success() {
        let tail = scrub(&String::from_utf8_lossy(&out.stderr), secrets);
        let msg = tail
            .lines()
            .rev()
            .find(|l| !l.trim().is_empty())
            .unwrap_or("")
            .to_string();
        return Err(match error_code(&msg) {
            Some(code) => anyhow!("vimeo:{code}"),
            None => anyhow!("{}", msg),
        });
    }
    Ok(String::from_utf8_lossy(&out.stdout).to_string())
}

/// O que sobrou de um download. `tail` já passou pelo `scrub`.
struct DownloadOutcome {
    file: Option<String>,
    meta: Option<(String, String)>,
    tail: String,
    success: bool,
}

/// Roda um download e conta o que aconteceu.
async fn run_download(
    bin: &Path,
    args: &[String],

View on GitHub (pinned to 8600b91f42)