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

  1. Check the inner error after this message for the actual unpack failure
  2. Delete and re-download the archive (a truncated file from a failed download is the usual cause)
  3. Verify free disk space at download_target
  4. 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

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


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/50c5aae881a81434. Report an issue: GitHub.