Zackriya-Solutions/meetily · error · anyhow::Error

Failed to start download

Error message

Failed to start download: {}

What it means

reqwest's client.get(model_url).send() failed at the transport layer: DNS resolution failure, TCP connect refused, TLS handshake error, or no route to host. This is distinct from a non-2xx response (that is error 193) — here no HTTP response was received at all. The request targets huggingface.co, so any blocker on that host triggers it.

Solutions

  1. Verify basic connectivity: curl -I https://huggingface.co from the same machine and user
  2. If behind a proxy, set HTTP_PROXY/HTTPS_PROXY correctly (reqwest honors them) or fix the broken proxy env var
  3. For TLS-intercepting proxies, add the proxy CA to the system trust store
  4. Retry after transient DNS/connection drops — the call is idempotent from byte 0
Defensive patterns

Strategy: retry

Validate before calling

// Rust: fail fast with a clear signal instead of a raw send() error
if reqwest::get("https://huggingface.co").await.is_err() {
    return Err(anyhow!("No network route to huggingface.co — check connectivity/proxy"));
}

Try / catch

let mut backoff = 1;
loop {
  match engine.download_model(name, cb.clone()).await {
    Ok(_) => break,
    Err(e) if String::from(&e).contains("Failed to start download") && backoff <= 4 => {
      tokio::time::sleep(Duration::from_secs(backoff)).await;
      backoff *= 2;
    }
    Err(e) => return Err(e),
  }
}

Prevention

When it happens

Trigger: Machine offline; DNS cannot resolve huggingface.co; corporate firewall or proxy blocking the CONNECT; TLS-intercepting proxy with an untrusted CA; IPv6-only misconfiguration.

Common situations: Firewalled enterprise networks; reqwest picking up a broken HTTP(S)_PROXY environment variable; captive portals; VPN split-tunnel rules excluding huggingface.co.

Related errors


AI-assisted analysis of Zackriya-Solutions/meetily@a2cb62e827 (2026-09-12). Data as JSON: /api/errors/d23372e64c82cb21. Report an issue: GitHub.

Appendix: source

Thrown at frontend/src-tauri/src/whisper_engine/whisper_engine.rs:1151

                .map_err(|e| anyhow!("Failed to create models directory: {}", e))?;
        }

        {
            let mut models = self.available_models.write().await;
            if let Some(model_info) = models.get_mut(model_name) {
                model_info.status = ModelStatus::Downloading { progress: 0 };
            }
        }

        let client = Client::builder()
            .user_agent(concat!("Meetily/", env!("CARGO_PKG_VERSION")))
            .build()
            .map_err(|e| anyhow!("Failed to create download client: {}", e))?;
        let response = tokio::select! {
            biased;
            _ = active_download.cancellation.cancelled() => return Err(DownloadCancelled.into()),
            response = client.get(model_url).send() => response
                .map_err(|e| anyhow!("Failed to start download: {}", e))?,
        };

        if !response.status().is_success() {
            return Err(anyhow!("Download failed with status: {}", response.status()));
        }

        let total_size = response.content_length().unwrap_or(0);
        let mut file = fs::File::create(file_path)
            .await
            .map_err(|e| anyhow!("Failed to create file: {}", e))?;

        use futures_util::StreamExt;
        let mut stream = response.bytes_stream();
        let mut downloaded = 0u64;
        let mut last_progress_report = 0u8;
        let mut last_report_time = std::time::Instant::now();

        if let Some(ref callback) = progress_callback {

View on GitHub (pinned to a2cb62e827)