Hmbown/CodeWhale · error

failed to extract ops origin/main archive

Error message

failed to extract ops origin/main archive

What it means

After piping the `git archive` output into `tar -x`, materialize_ops_origin_main checks tar's exit status. A non-zero status from tar means the ops archive could not be extracted to the destination directory, so the ops tree is not available.

Solutions

  1. Check the destination directory exists and is writable (permissions, disk space)
  2. Re-run after a successful `git fetch origin main` to get a fresh archive
  3. Run `git archive origin/main | tar -t` manually to see tar's diagnostic
  4. Ensure a compatible `tar` binary is on PATH
Defensive patterns

Strategy: try-catch

Validate before calling

let dest_ok = dest.exists() && dest.permissions().ok().map(|p| !p.readonly()).unwrap_or(false);

Try / catch

match materialize_ops_origin_main(dest) { Err(e) if e.to_string().contains("failed to extract") => { fs_err::remove_dir_all(dest).ok(); fs_err::create_dir_all(dest)?; retry_once(materialize_ops_origin_main, dest)?; } other => other?, }

Prevention

When it happens

Trigger: tar exits non-zero while extracting the archive: destination directory not writable, disk full, tar incompatible with the stream, or truncated/corrupt archive stdout.

Common situations: Read-only or missing destination directory; tar/gnu-tar version differences; interrupted pipe between git archive and tar; insufficient disk space.

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 Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/9aa30b97a3ac4af2. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/operate.rs:913

            String::from_utf8_lossy(&archive.stderr).trim()
        );
    }
    let mut child = Command::new("tar")
        .arg("-x")
        .arg("-C")
        .arg(&dest)
        .stdin(Stdio::piped())
        .stdout(Stdio::null())
        .stderr(Stdio::piped())
        .spawn()
        .context("tar extract ops origin/main")?;
    if let Some(mut stdin) = child.stdin.take() {
        use std::io::Write;
        stdin.write_all(&archive.stdout)?;
    }
    let status = child.wait()?;
    if !status.success() {
        anyhow::bail!("failed to extract ops origin/main archive");
    }
    if !marker.is_file() {
        anyhow::bail!("ops origin/main archive missing {CHECK_AUTO_MERGE_SCRIPT}");
    }
    Ok(dest)
}

pub fn default_operate_dir() -> PathBuf {
    if let Ok(path) = std::env::var("CODEWHALE_OPERATE_DIR") {
        let trimmed = path.trim();
        if !trimmed.is_empty() {
            return PathBuf::from(trimmed);
        }
    }
    crate::automation_manager::default_automations_dir()
        .parent()
        .map(|parent| parent.join("operate"))
        .unwrap_or_else(|| PathBuf::from("operate"))

View on GitHub (pinned to 73e0f67d83)