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
- Free up disk space on the destination volume (check with df) and resume — the .part file allows resuming
- Verify the destination path's volume is mounted and writable
- Check disk health and filesystem errors if EIO recurs (dmesg / SMART)
- Reduce concurrency if parallel downloads are exhausting space or file locks
- 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
- Check available space (file size from Content-Length) before starting large downloads
- Point temp/.part files at a volume with guaranteed free space
- Monitor disk space during long downloads and pause before ENOSPC
- Verify external/NAS volumes remain mounted and writable for the download's duration
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
- rename .part to final failed
- Failed to move into place
- Failed to replace
- gallery-dl binary not found after download
- nao foi possivel mover a instalacao para o lugar
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)