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

Failed to preserve {} after stream error: {}

Error message

Failed to preserve {} after stream error: {}

What it means

Raised when the artifact's HTTP byte stream itself yields an error (`Ok(Some(Err(error)))` from `bytes_stream()`), e.g. a connection reset or body read failure mid-download. The engine flushes the BufWriter to keep partial bytes resumable; if that flush fails with `flush_error`, this message wrapping the flush error is produced (the original stream error is then lost).

Source

Thrown at frontend/src-tauri/src/parakeet_engine/parakeet_engine.rs:1021

                        })?;
                        return Err(DownloadCancelled.into());
                    }
                    chunk = timeout(Duration::from_secs(30), stream.next()) => chunk,
                };
                let chunk = match next_chunk {
                    Err(_) => {
                        writer.flush().await.map_err(|error| {
                            anyhow!("Failed to preserve {} after timeout: {}", artifact.filename, error)
                        })?;
                        return Err(anyhow!(
                            "Download timeout for {}: no data received for 30 seconds",
                            artifact.filename
                        ));
                    }
                    Ok(None) => break,
                    Ok(Some(Err(error))) => {
                        writer.flush().await.map_err(|flush_error| {
                            anyhow!(
                                "Failed to preserve {} after stream error: {}",
                                artifact.filename,
                                flush_error
                            )
                        })?;
                        return Err(anyhow!("Download stream failed for {}: {}", artifact.filename, error));
                    }
                    Ok(Some(Ok(chunk))) => chunk,
                };

                let chunk_bytes = chunk.len() as u64;
                let next_artifact_bytes = artifact_bytes
                    .checked_add(chunk_bytes)
                    .ok_or_else(|| anyhow!("{} size overflow", artifact.filename))?;
                if next_artifact_bytes > artifact.exact_bytes {
                    writer.flush().await.map_err(|error| {
                        anyhow!("Failed to preserve {} after overlong response: {}", artifact.filename, error)
                    })?;

View on GitHub (pinned to a2cb62e827)

Solutions

  1. Retry the download — the engine appends from the preserved partial file via Range resume, so a mid-stream reset only costs the lost interval.
  2. Diagnose the stream cause: run with `RUST_LOG=debug` and check reqwest/hyper logs for `connection reset`, `broken pipe`, or TLS errors; fix that layer (proxy, MTU, VPN).
  3. Free disk space / verify the models directory is writable — this exact message only appears when the post-error flush fails, almost always storage-side (disk full, locked file, unplugged drive).
  4. Exclude the models directory from antivirus/indexing to prevent the partial file from being locked during the flush.
  5. If the CDN habitually truncates, wrap the engine call in a retry loop; on repeated truncation at the same offset, delete the partial file so the next attempt starts clean.
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight connectivity + TLS sanity to the artifact host
let resp = reqwest::Client::new().head(&file_url)
    .timeout(Duration::from_secs(10)).send().await
    .map_err(|e| format!("cannot reach artifact host: {e}"))?;
if !resp.status().is_success() {
    return Err(format!("artifact host returned {}", resp.status()));
}

Try / catch

let mut failures = 0;
loop {
    match engine.download_models(&artifacts, &token).await {
        Err(e) if e.to_string().contains("after stream error") && failures < 3 => {
            failures += 1;
            tokio::time::sleep(Duration::from_secs(2u64.pow(failures))).await;
        }
        Err(e) if e.to_string().contains("after stream error") => {
            // repeated truncation: drop the suspect partial file and start clean
            let _ = tokio::fs::remove_file(&partial_path).await;
            engine.download_models(&artifacts, &token).await?;
            break;
        }
        other => break other,
    }
}

Prevention

When it happens

Trigger: The reqwest response body errors mid-transfer: connection reset by peer, TLS handshake/renegotiation failure, server closed the connection early (truncated response), reqwest timeout on the connection, DNS/network flaps during the transfer — and the post-error flush to the local file then fails too.

Common situations: Router/wifi drops mid-download resetting the TCP connection; server (HF CDN) closes the body early under load; corporate proxy TLS-intercepts and kills long transfers; disk becomes full or the partial file gets locked right as the stream fails, so preservation also fails.

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 Zackriya-Solutions/meetily@a2cb62e827 (2026-09-12). Data as JSON: /api/errors/87f62a0d2665f693. Report an issue: GitHub.