rust-lang/rust · error

{context}: {err}

Error message

{context}: {err}

What it means

This is the io_error_context helper, not a standalone error. It wraps an underlying io::Error with a descriptive prefix so that low-level filesystem failures during archive writing carry context about which operation failed. Within archive.rs it prefixes two operations: 'failed to rename archive file' (the atomic rename of the temp archive to its final path) and 'failed to remove temporary directory' (cleaning up the temp dir). The {err} part is the original OS error.

Source

Thrown at compiler/rustc_codegen_ssa/src/back/archive.rs:721

        let any_entries = !entries.is_empty();
        drop(entries);
        // Drop src_archives to unmap all input archives, which is necessary if we want to write the
        // output archive to the same location as an input archive on Windows.
        drop(self.src_archives);

        fs::rename(archive_tmpfile_path, output)
            .map_err(|err| io_error_context("failed to rename archive file", err))?;
        archive_tmpdir
            .close()
            .map_err(|err| io_error_context("failed to remove temporary directory", err))?;

        Ok(any_entries)
    }
}

fn io_error_context(context: &str, err: io::Error) -> io::Error {
    io::Error::new(io::ErrorKind::Other, format!("{context}: {err}"))
}

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Ensure TMPDIR / cargo target dir and the final output path are on the same filesystem/mount.
  2. Check write permissions and free disk space on the output directory.
  3. On Windows, disable or exclude the target directory from antivirus/on-access scanning and close editors/IDEs holding the file.
  4. Retry the build after clearing stale locks; if it persists, capture the OS errno from {err} and address it specifically.
Defensive patterns

Strategy: try-catch

Validate before calling

// Generic wrapper around an underlying archive error.
// Pre-flight: try to open and parse the archive so the
// underlying error surfaces before rustc sees it.
fn archive_preflight(path: &std::path::Path) -> Result<(), String> {
    std::process::Command::new("ar")
        .args(["t", path.to_str().unwrap()])
        .output()
        .map_err(|e| e.to_string())
        .and_then(|o| {
            if o.status.success() { Ok(()) }
            else { Err(format!("{}", String::from_utf8_lossy(&o.stderr))) }
        })
}

Type guard

fn is_openable_archive(path: &std::path::Path) -> bool {
    archive_preflight(path).is_ok()
}

Try / catch

// The message is "{context}: {err}"; parse the context to classify.
let stderr = String::from_utf8_lossy(&output.stderr);
for line in stderr.lines() {
    if let Some((ctx, err)) = line.split_once(": ") {
        report(ResolveError::Archive { context: ctx.into(), detail: err.into() });
    }
}

Prevention

When it happens

Trigger: Produced when fs::rename of the freshly written temp archive to the output path fails, or when tempdir cleanup fails. The prefix tells you which step; the suffix carries the OS-level reason (permission denied, cross-device, busy, etc.).

Common situations: Output path on a different filesystem/mount than the temp dir, making the atomic rename a cross-device move that the OS rejects. Permission/ownership mismatch on the target directory. Antivirus or file-locking software (common on Windows) holding the output file open. The destination being read-only or on a full disk.

Related errors


AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03). Data as JSON: /data/errors/2e647dcd56b71679.json. Report an issue: GitHub.