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
- Parse the code after the `vimeo:` prefix and map it to a user-facing message (private, geo-blocked, etc.).
- For login-required codes, supply cookies/credentials (`--cookies-from-browser` or the app's auth option).
- For geo/removed content, there is no retry fix — inform the user the video is unavailable.
- 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
- Match on the vimeo:<code> prefix instead of free text — it is the stable contract
- Keep yt-dlp updated so recognized error classifications stay accurate
- Provide cookie/auth options up front for private or members-only Vimeo content
- Apply backoff on rate-limit codes before retrying enumeration
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
- o yt-dlp devolveu um JSON que não deu para ler
- o yt-dlp não está disponível
- não foi possível iniciar o yt-dlp
- {}
- vimeo:unavailable
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)