tonhowtf/omniget · error

Download stream error: {}

Error message

Download stream error: {}

What it means

While reading the response body stream, a chunk arrived as Ok(Some(Err(e))) — i.e. reqwest/hyper reported a mid-stream network error. The downloader flushes the partial file (so the .part can be resumed later) and returns the underlying transport error wrapped with this message. Distinguish it from the separate timeout arm, which fires when no chunk arrives at all within CHUNK_TIMEOUT (30s).

Solutions

  1. Simply retry: download_attempt's retry logic resumes from the flushed .part file via the Range header
  2. Enable/verify resume support — a valid .part file turns mid-stream drops into cheap recoveries
  3. If errors recur on the same host, try HTTP/1.1 (disable HTTP/2) or route around a failing proxy
  4. Check network stability (VPN, firewall, mobile handoff) for repeated resets
  5. Add your own backoff around the whole download call if the network is known-unreliable

Example fix

// before: single-shot download fails on any blip
single_stream(&client, url, &part_path, cancel).await?;
// after: rely on resumable retries
let mut attempt = 0;
loop {
    match single_stream(&client, url, &part_path, cancel).await {
        Ok(()) => break,
        Err(e) if e.to_string().starts_with("Download stream error") && attempt < 5 => {
            attempt += 1;
            tokio::time::sleep(Duration::from_secs(2u64.pow(attempt))).await; // resume from .part
        }
        Err(e) => return Err(e),
    }
}
Defensive patterns

Strategy: retry

Try / catch

match download(url, path).await {
    Err(e) if e.to_string().starts_with("Download stream error") => {
        // connection broke mid-stream; .part was flushed, so retry resumes via Range
        retry_with_backoff(|| download(url, path), max_retries = 5).await?;
    }
    r => r?,
}

Prevention

When it happens

Trigger: The HTTP connection broke mid-body: server closed the connection prematurely (incomplete chunked encoding), TCP reset, TLS handshake/alert mid-stream, proxy dropped the connection, or a reqwest::Error from hyper while polling stream.next().

Common situations: Flaky Wi-Fi or mobile networks dropping long downloads; CDN origin closing idle-but-active connections; VPN/proxy interruptions; server-side connection limits killing long transfers; HTTP/2 GOAWAY from the server.

Related errors


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

Appendix: source

Thrown at src-tauri/omniget-core/src/core/direct_downloader.rs:593

                                .min(95.0),
                            None,
                        ),
                    };
                    let _ = progress_tx
                        .send(ProgressUpdate::rich(
                            percent,
                            Some(downloaded),
                            total_size.filter(|t| *t > 0),
                            speed,
                            eta,
                        ))
                        .await;
                    last_emit = std::time::Instant::now();
                }
            }
            Ok(Some(Err(e))) => {
                file.flush()?;
                return Err(anyhow!("Download stream error: {}", e));
            }
            Ok(None) => break,
            Err(_) => {
                file.flush()?;
                return Err(anyhow!(
                    "Download timeout — no data received for 30 seconds"
                ));
            }
        }
    }

    file.flush()?;
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;

View on GitHub (pinned to 8600b91f42)