ducaale/xh · error

Incomplete download: size=

Error message

Incomplete download: size={}; downloaded={}

What it means

After the download stream ends, download_file compares the bytes actually written against the expected total length. If fewer bytes were received than the server promised, the download is declared incomplete and this error is raised.

Solutions

  1. Retry the download using the resume option so it continues from the last byte received.
  2. Improve network stability or retry with a longer/robust connection configuration.
  3. Check whether a proxy or firewall is cutting long-lived connections; adjust its idle timeout.
  4. Verify free disk space and that the target file is writable, then resume again.

Example fix

// before
let result = download_file(url, None);
// after
let result = match download_file(url, saved_offset) {
    Err(e) if is_incomplete(&e) => download_file(url, saved_offset_from_partial),
    r => r,
};
Defensive patterns

Strategy: retry

Validate before calling

let expected = content_length_response_size_estimate; // from headers
let downloaded = std::fs::metadata(partial_path)?.len();
if downloaded < expected { /* resume before declaring success */ }

Try / catch

loop {
    match download_file(url, current_offset()) {
        Err(e) if e.to_string().contains("Incomplete download") && retries < 3 => { retries += 1; continue; }
        other => break other,
    }
}

Prevention

When it happens

Trigger: The response body stream terminates early (connection closed, timeout, server truncation) so total_downloaded_length < total_length at the end of download_file.

Common situations: Flaky Wi-Fi or mobile connections dropping mid-transfer; server/proxy idle timeouts killing long downloads; disk-full is usually a separate error but connection resets are the typical cause; very large files over unstable links.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of ducaale/xh@2404aceecc (2026-09-13). Data as JSON: /api/errors/de876064ad0abe6f. Report an issue: GitHub.

Appendix: source

Thrown at src/download.rs:293

        let time_taken = starting_time.elapsed();
        if !time_taken.is_zero() {
            eprintln!(
                "{verb}. {} in {:.5}s ({}/s)",
                HumanBytes(downloaded_length),
                time_taken.as_secs_f64(),
                HumanBytes((downloaded_length as f64 / time_taken.as_secs_f64()) as u64)
            );
        } else {
            eprintln!("{verb}. {}", HumanBytes(downloaded_length));
        }
        if incomplete.is_some() {
            // Separate the summary from the error message that follows.
            eprintln!();
        }
    }

    if let Some(total_length) = incomplete {
        return Err(anyhow!(
            "Incomplete download: size={}; downloaded={}",
            total_length,
            total_downloaded_length
        ));
    }

    Ok(())
}

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

    #[test]
    fn content_range_parsing() {
        let expected = vec![
            (2, "bytes 2-5/6", Some(6)),
            (2, "bytes 2-5/*", Some(6)),

View on GitHub (pinned to 2404aceecc)