windmill-labs/windmill · error
Failed to extract repository archive: {e}
Error message
Failed to extract repository archive: {e} What it means
The blocking task that unpacks the downloaded repository archive failed, or the tokio task itself panicked/was cancelled — the JoinError is wrapped with this message. The double `??` means both JoinError and the inner unpack error surface.
Source
Thrown at backend/windmill-worker/src/ansible_executor.rs:499
let mut stream = response.bytes_stream();
while let Some(chunk) = stream.next().await {
let chunk = chunk.map_err(|e| anyhow!("Failed to read repository archive: {e}"))?;
file.write_all(&chunk).await?;
}
file.flush().await?;
drop(file);
// Dropping the join handle detaches the blocking task rather than
// stopping it, so the flag is what a cancelled job uses to reach the
// extraction loop. The guard sets it when this future is dropped.
let aborted = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false));
let _abort_on_drop = AbortOnDrop(aborted.clone());
let unpack_archive = download_archive.clone();
tokio::task::spawn_blocking(move || {
unpack_repo_archive(&unpack_archive, &download_target, &aborted)
})
.await
.map_err(|e| anyhow!("Failed to extract repository archive: {e}"))??;
Ok(commit)
};
// Through the job poller, like the git clone paths: the download has no
// wall-clock bound of its own, so this is what makes a cancelled or
// timed-out run stop occupying the worker.
let commit = run_future_with_polling_update_job_poller(
job.id,
job.timeout,
conn,
mem_peak,
canceled_by,
fetch,
worker_name,
&job.workspace_id,
&mut Some(occupancy_metrics),
Box::pin(futures::stream::once(async { 0 })),View on GitHub (pinned to e474e8803c)
Solutions
- Check the inner error after this message for the actual unpack failure
- Delete and re-download the archive (a truncated file from a failed download is the usual cause)
- Verify free disk space at download_target
- Confirm the archive format is supported by unpack_repo_archive (tar/zip as expected)
Defensive patterns
Strategy: fallback
Validate before calling
# before extracting tar -tzf "$ARCHIVE" >/dev/null 2>&1 || echo "archive corrupt/truncated" df -h "$(dirname "$DOWNLOAD_TARGET")" | tail -n1 # disk space
Try / catch
match fetch_repo_archive(...).await {
Err(e) if e.to_string().contains("Failed to extract repository archive") => {
eprintln!("delete archive and re-download: {e:#}");
// fallback: re-fetch then retry once
}
other => other?,
} Prevention
- Verify archive integrity after download before unpacking
- Monitor worker disk space
- Re-download rather than reuse archives from interrupted runs
- Keep the abort/cancellation signal consistent between download and unpack phases
When it happens
Trigger: fetch_repo_archive spawns unpack_repo_archive via spawn_blocking; the archive is corrupt/truncated (e.g. from error 1008's download), the disk is full, or the blocking task panicked.
Common situations: Partial archive saved from an interrupted download; insufficient disk space in the worker; unsupported archive format; abort signal triggering early exit.
Related errors
- could not record run ${experiment_id}: ${res.status} ${await
- Aborted from C
- fputs is not supported
- fputc is not supported
- fdopen is not supported
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/50c5aae881a81434.
Report an issue: GitHub.