tonhowtf/omniget · error · anyhow::Error

Failed to start gallery-dl

Error message

Failed to start gallery-dl: {}

What it means

Spawning the gallery-dl child process failed, so the download cannot proceed. `Command::spawn()` returned an OS error (wrapped into this anyhow error) — typically the binary path is invalid or not executable.

Solutions

  1. Check the wrapped OS error message to confirm the cause (NotFound vs PermissionDenied).
  2. Re-run `ensure_gallerydl()` (or restart the app) so a valid, existing binary path is used.
  3. Ensure the gallery-dl binary has the executable bit: `chmod +x <path-to-gallery-dl>`.
  4. On macOS/Windows, approve/quarantine-unblock the binary so the sandboxed app may execute it.

Example fix

// before
let bin = ensure_gallerydl().await.ok_or_else(|| anyhow!("gallery-dl not available"))?;
let mut child = cmd.spawn().map_err(|e| anyhow!("Failed to start gallery-dl: {}", e))?;
// after
let bin = ensure_gallerydl().await.ok_or_else(|| anyhow!("gallery-dl not available"))?;
if !bin.exists() {
    anyhow::bail!("gallery-dl binary missing at {:?}, re-installing", bin);
}
let mut child = cmd.spawn().map_err(|e| anyhow!("Failed to start gallery-dl at {:?}: {}", bin, e))?;
Defensive patterns

Strategy: retry

Validate before calling

// Rust, before spawning
let bin = omniget_core::core::dependencies::ensure_gallerydl().await.ok_or_else(|| anyhow!("gallery-dl missing"))?;
use std::os::unix::fs::PermissionsExt;
let md = std::fs::metadata(&bin).map_err(|e| anyhow!("gallery-dl binary missing at {:?}: {}", bin, e))?;
if md.permissions().mode() & 0o111 == 0 {
    std::fs::set_permissions(&bin, std::fs::Permissions::from_mode(0o755))?;
}

Try / catch

// Rust
let child = match cmd.spawn() {
    Ok(c) => c,
    Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
        // re-ensure the binary, then retry once
        let _ = ensure_gallerydl().await;
        cmd.spawn().map_err(|e| anyhow!("Failed to start gallery-dl after re-ensure: {}", e))?
    }
    Err(e) => return Err(anyhow!("Failed to start gallery-dl: {}", e)),
};

Prevention

When it happens

Trigger: Calling gallerydl `download` after `ensure_gallerydl()` returned a path that no longer exists, was replaced mid-run, lacks the executable bit, or cannot be executed due to sandbox/permission restrictions.

Common situations: Binary auto-updated/deleted between ensure and spawn, downloaded binary missing +x permissions, macOS Gatekeeper/app-sandbox blocking the spawned executable, or antivirus quarantining the binary on Windows.

Related errors


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

Appendix: source

Thrown at src-tauri/src/platforms/gallerydl/mod.rs:238

            if std::fs::create_dir_all(&archive_dir).is_ok() {
                cmd.arg("--download-archive")
                    .arg(archive_dir.join("gallery-dl.txt"));
            }
            let cookie_file = data_dir.join("chrome-extension-cookies.txt");
            if std::fs::metadata(&cookie_file)
                .map(|m| m.len() > 0)
                .unwrap_or(false)
            {
                cmd.arg("--cookies").arg(&cookie_file);
            }
        }

        cmd.arg("--").arg(&url);

        cmd.kill_on_drop(true);
        let mut child = cmd
            .spawn()
            .map_err(|e| anyhow!("Failed to start gallery-dl: {}", e))?;

        let stdout = child
            .stdout
            .take()
            .ok_or_else(|| anyhow!("No stdout from gallery-dl"))?;
        let stderr_pipe = child
            .stderr
            .take()
            .ok_or_else(|| anyhow!("No stderr from gallery-dl"))?;

        let started_at = SystemTime::now();

        let progress_tx = progress.clone();
        let reader_task = tokio::spawn(async move {
            let mut lines = BufReader::new(stdout).lines();
            let mut count: u64 = 0;
            let mut last_emit = std::time::Instant::now();
            while let Ok(Some(line)) = lines.next_line().await {

View on GitHub (pinned to 8600b91f42)