tonhowtf/omniget · error

Write error (disk full?)

Error message

Write error (disk full?): {}

What it means

Each downloaded chunk is written to the .part file with file.write_all; if the OS write fails, the downloader wraps the std::io::Error with this message. The 'disk full?' hint reflects the most common cause — insufficient free space — though it can also be I/O errors, quota limits, or a removed file handle.

Solutions

  1. Free up disk space on the destination volume (check with df) and resume — the .part file allows resuming
  2. Verify the destination path's volume is mounted and writable
  3. Check disk health and filesystem errors if EIO recurs (dmesg / SMART)
  4. Reduce concurrency if parallel downloads are exhausting space or file locks
  5. Move the download target to a volume with enough space for the full file size before restarting

Example fix

// before: starting a download without a space check
let resp = client.get(url).send().await?;
download(resp, &part_path).await?;
// after: pre-flight free-space check
let expected = content_length(&resp);
let available = fs2::available_space(parent_dir_of(&part_path))?;
if available < expected + 100 * 1024 * 1024 {
    anyhow::bail!("Not enough disk space: need {}, have {}", expected, available);
}
download(resp, &part_path).await?;
Defensive patterns

Strategy: validation

Validate before calling

let needed = content_length_hint; // from HEAD/Content-Length
let free = fs2::available_space(&dest_dir)?;
if free < needed + margin { bail!("insufficient disk space: need {}, free {}", needed, free); }

Try / catch

match download(url, path).await {
    Err(e) if e.to_string().starts_with("Write error (disk full?)") => {
        free_up_space_or_change_target()?;
        resume_download(url, path).await?; // .part allows resuming
    }
    r => r?,
}

Prevention

When it happens

Trigger: file.write_all(&chunk) returned Err while streaming: ENOSPC (no space left on device), EDQUOT (quota exceeded), EIO (disk error), or writing to a file/destination that was deleted or on a disconnected mount (e.g. unmounted external drive).

Common situations: Downloading multi-GB files to a nearly full disk; user quota limits on network shares; the destination drive (USB/NAS) disconnecting mid-download; antivirus or backup software locking the file.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


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

Appendix: source

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

    let mut last_emit = std::time::Instant::now();
    let mut speed_anchor_bytes = downloaded;
    let mut speed_anchor_time = std::time::Instant::now();
    let mut speed_ema: f64 = 0.0;

    loop {
        if let Some(token) = cancel {
            if token.is_cancelled() {
                file.flush()?;
                return Err(anyhow!("Download cancelled"));
            }
        }

        let chunk_result = tokio::time::timeout(CHUNK_TIMEOUT, stream.next()).await;
        match chunk_result {
            Ok(Some(Ok(chunk))) => {
                file.write_all(&chunk)
                    .map_err(|e| anyhow!("Write error (disk full?): {}", e))?;
                downloaded += chunk.len() as u64;

                if last_emit.elapsed() >= std::time::Duration::from_millis(250) {
                    let dt = speed_anchor_time.elapsed().as_secs_f64();
                    if dt >= 0.2 {
                        let instant = (downloaded.saturating_sub(speed_anchor_bytes)) as f64 / dt;
                        speed_ema = if speed_ema > 0.0 {
                            speed_ema * 0.6 + instant * 0.4
                        } else {
                            instant
                        };
                        speed_anchor_bytes = downloaded;
                        speed_anchor_time = std::time::Instant::now();
                    }
                    let speed = (speed_ema > 0.0).then_some(speed_ema);
                    let (percent, eta) = match total_size {
                        Some(total) if total > 0 => {
                            let pct = (downloaded as f64 / total as f64) * 100.0;

View on GitHub (pinned to 8600b91f42)