rust-lang/cargo · error · anyhow::Error

failed to open

Error message

failed to open `{}`: {}

What it means

Thrown by cargo_clean when fs::File::open on target/CACHEDIR.TAG fails, after earlier checks already confirmed the path is a regular non-symlink file. The format string interpolates the path and the underlying io::Error, so this is an OS-level open failure (permissions, race with deletion, filesystem error) rather than a missing-file mistake, which is caught earlier.

Solutions

  1. Re-run `cargo clean` with no concurrent cargo process active.
  2. Check ownership and permissions of target/CACHEDIR.TAG and fix with chmod/chown if owned by another user.
  3. If the filesystem is read-only or sandboxed, remount writable or relax the sandbox for the target dir.
  4. As a last resort, remove the target directory manually: `rm -rf target`.

Example fix

# before (target owned by root from a sudo build)
cargo clean
# after
sudo chown -R $USER:$USER target && cargo clean
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify target dir is cleanable before invoking cargo clean.
use std::os::unix::fs::PermissionsExt;
fn writable(p: &std::path::Path) -> bool {
    std::fs::metadata(p).map(|m| m.permissions().mode() & 0o200 != 0).unwrap_or(false)
}

Try / catch

// Wrap cargo clean invocations and fall back to manual removal on open failure.
match std::process::Command::new("cargo").arg("clean").status() {
    Ok(s) if s.success() => {},
    _ => { let _ = std::fs::remove_dir_all("target"); }
}

Prevention

When it happens

Trigger: Another process deletes target/ between the is_file() check and the open() call; file permissions deny read access to the current user; a read-only filesystem mount; antivirus/container sandbox blocking open; CACHEDIR.TAG exists but is held exclusively on Windows.

Common situations: Running `cargo clean` while a build or IDE is concurrently writing to target/; CI runners with restricted perms; NFS/network filesystems with stale file handles; switched user / sudo leaving target owned by root.

Related errors


AI-assisted analysis of rust-lang/cargo@98a09e7e7d (2026-08-11). Data as JSON: /api/errors/68e9219d2df02a72. Report an issue: GitHub.

Appendix: source

Thrown at src/ops/cargo_clean.rs:172

    Ok(())
}

fn validate_target_dir_tag(target_dir_path: &Path) -> CargoResult<()> {
    const TAG_SIGNATURE: &[u8] = b"Signature: 8a477f597d28d172789f06886806bc55";

    let tag_path = target_dir_path.join("CACHEDIR.TAG");

    // per https://bford.info/cachedir the tag file must not be a symlink
    if tag_path.is_symlink() {
        bail!("expect `CACHEDIR.TAG` to be a regular file, got a symlink");
    }

    if !tag_path.is_file() {
        bail!("missing or invalid `CACHEDIR.TAG` file");
    }

    let mut file = fs::File::open(&tag_path)
        .map_err(|err| anyhow::anyhow!("failed to open `{}`: {}", tag_path.display(), err))?;

    let mut buf = [0u8; TAG_SIGNATURE.len()];
    match file.read_exact(&mut buf) {
        Ok(()) if &buf[..] == TAG_SIGNATURE => {}
        Err(e) if e.kind() != io::ErrorKind::UnexpectedEof => {
            bail!("failed to read `{}`: {e}", tag_path.display());
        }
        _ => {
            bail!("invalid signature in `CACHEDIR.TAG` file");
        }
    }

    Ok(())
}

fn clean_specs(
    clean_ctx: &mut CleanContext<'_>,
    ws: &Workspace<'_>,

View on GitHub (pinned to 98a09e7e7d)