{"record":{"id":"9227e49cfe8f199c","repo":"tonhowtf/omniget","slug":"gallery-dl-binary-not-found-after-download","errorCode":null,"errorMessage":"gallery-dl binary not found after download","messagePattern":"gallery-dl binary not found after download","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/dependencies.rs","lineNumber":855,"sourceCode":"    let bytes = response.bytes().await?;\n    let data = bytes.to_vec();\n    let target_clone = target.clone();\n    tokio::task::spawn_blocking(move || -> anyhow::Result<()> {\n        std::fs::write(&target_clone, &data)?;\n        #[cfg(unix)]\n        {\n            use std::os::unix::fs::PermissionsExt;\n            let mut perm = std::fs::metadata(&target_clone)?.permissions();\n            perm.set_mode(0o755);\n            std::fs::set_permissions(&target_clone, perm)?;\n        }\n        Ok(())\n    })\n    .await\n    .map_err(|e| anyhow!(\"Spawn blocking failed: {}\", e))??;\n\n    if !target.exists() {\n        return Err(anyhow!(\"gallery-dl binary not found after download\"));\n    }\n\n    Ok(target)\n}\n\npub async fn ensure_aria2c() -> Option<PathBuf> {\n    if let Some(path) = find_tool(\"aria2c\").await {\n        return Some(path);\n    }\n\n    // Auto-download only on Windows\n    #[cfg(target_os = \"windows\")]\n    {\n        match download_aria2c().await {\n            Ok(path) => return Some(path),\n            Err(e) => {\n                tracing::warn!(\"Failed to download aria2c: {}\", e);\n            }","sourceCodeStart":837,"sourceCodeEnd":873,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/dependencies.rs#L837-L873","documentation":"After the spawn_blocking write step completes without error, download_gallerydl verifies the target binary path exists. If the file is missing on disk it throws 'gallery-dl binary not found after download', an internal consistency check: the task reported success but produced no file.","triggerScenarios":"The spawn_blocking closure returned Ok without actually writing the file (e.g. a skipped/conditional write branch), the target path was moved/deleted between write and the existence check, or the binary was written to a different path than `target` (path/perm_dir mismatch).","commonSituations":"Antivirus quarantining the freshly downloaded executable immediately after write; the extraction/permissions branch silently skipping the rename/write; target path computed with a different bin_name than where bytes were written; network drives with delayed visibility.","solutions":["Check whether antivirus/EDR quarantined the new binary and add an exclusion for the app's bin directory","Log the exact target path and verify manually that it exists after a failed run","Ensure the write path inside spawn_blocking and `target` are built from the same bin_name/path logic","Re-run the download — a transient FS sync issue on network shares can delay visibility","Add a retry or re-download step when the existence check fails"],"exampleFix":"// before\nif !target.exists() {\n    return Err(anyhow!(\"gallery-dl binary not found after download\"));\n}\n// after\nif !target.exists() {\n    anyhow::bail!(\n        \"gallery-dl binary not found at {} after download (AV quarantine or path mismatch?)\",\n        target.display()\n    );\n}","handlingStrategy":"validation","validationCode":"let target = bin_dir.join(bin_name(\"gallery-dl\"));\nif !bin_dir.exists() || !bin_dir.join(bin_name(\"gallery-dl\")).parent().map(|p| p.exists()).unwrap_or(false) {\n    return Err(anyhow!(\"target directory {} missing before download\", bin_dir.display()));\n}","typeGuard":"fn binary_ready(target: &std::path::Path) -> bool {\n    target.is_file() && std::fs::metadata(target).map(|m| m.len() > 0).unwrap_or(false)\n}","tryCatchPattern":"match ensure_gallerydl().await {\n    Ok(p) => p,\n    Err(e) if e.to_string().contains(\"binary not found after download\") => {\n        // file vanished post-write: suspect AV quarantine or path mismatch\n        log::error!(\"gallery-dl missing at target after install: {e}\");\n        Err(anyhow!(\"installed binary was removed (antivirus?) — add exclusion and retry\"))\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Whitelist the app's managed-bin directory in antivirus/EDR software","Assert the write path and existence-check path are derived from the same bin_name() call","Verify file size > 0 after download, not just existence","Build the target path in one place and pass it into both the writer and the checker"],"tags":["filesystem","download","invariant","dependency-management"],"backgroundTag":"file-not-found","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}