rust-lang/cargo · error
unable to read .cargo-ok file at
Error message
unable to read .cargo-ok file at {path:?}: {e} What it means
When unpacking a `.crate` tarball, Cargo reads the marker `.cargo-ok` file inside the unpack directory to detect a previously-completed unpack. If reading that file fails with an I/O error other than `NotFound` (e.g. permission denied, disk error), Cargo bails rather than guessing. `NotFound` is tolerated (first unpack).
Solutions
- Fix permissions: `chown -R $USER ~/.cargo` and `chmod -R u+rwX ~/.cargo/registry/src`.
- Remove the corrupt unpack directory: `rm -rf ~/.cargo/registry/src/<index>/<pkg>-<ver>` then rebuild.
- Disable/reconfigure antivirus or SELinux that may block reads under `~/.cargo`.
- Free disk space / remount read-write if the filesystem is read-only.
Example fix
# before: permission-denied / corrupt .cargo-ok $ cargo build error: unable to read .cargo-ok file at ".../.cargo-ok": Permission denied # after $ chmod -R u+rwX ~/.cargo/registry/src $ rm -rf ~/.cargo/registry/src/<index>/<pkg>-<ver> $ cargo build
Defensive patterns
Strategy: try-catch
Validate before calling
fn can_read_ok_file(path: &Path) -> bool {
match std::fs::read_to_string(path) {
Ok(_) => true,
Err(e) if e.kind() == std::io::ErrorKind::NotFound => true,
Err(_) => false,
}
} Type guard
fn ok_file_accessible(path: &std::path::Path) -> bool {
std::fs::metadata(path).map_or(true, |_| std::fs::read_to_string(path).is_ok())
} Try / catch
match fs::read_to_string(&path) {
Ok(s) => /* parse */,
Err(e) if e.kind() == io::ErrorKind::NotFound => {},
Err(e) => {
// attempt recovery: fix perms or wipe the unpack dir, then retry once
let _ = fs::remove_dir_all(dst.as_path_unlocked());
return unpack(...);
}
} Prevention
- Keep `~/.cargo/registry/src` writable and owned by the build user.
- Remove half-unpacked source dirs after a crash before rebuilding.
- Disable/loosen SELinux/apparmor rules that block reads under cargo dirs.
- Ensure adequate disk space and write permissions in CI.
When it happens
Trigger: In the unpack flow, `fs::read_to_string(<dst>/.cargo-ok)` returns an I/O error whose `kind()` is not `NotFound`. Causes: permission denied, I/O error, broken symlink, or filesystem corruption at the unpack path.
Common situations: Permissions on `~/.cargo/registry/src` wrong (read-only or owned by another user); a broken `.cargo-ok` symlink left by a crashed unpack; antivirus/SELinux blocking reads; full or read-only filesystem; NFS hiccup.
Related errors
- failed to open
- failed to read path
- invalid tarball downloaded, contains a file at
- invalid tarball downloaded, contains an entry at
- local registry index path is not a directory
AI-assisted analysis of rust-lang/cargo@98a09e7e7d (2026-08-11).
Data as JSON: /api/errors/ea6580d267e3b020.
Report an issue: GitHub.
Appendix: source
Thrown at src/sources/registry/mod.rs:586
.mark_registry_src_used(global_cache_tracker::RegistrySrc {
encoded_registry_name: self.name,
package_dir: package_dir.into(),
size: None,
});
return Ok(unpack_dir.to_path_buf());
}
_ => {
if ok == "ok" {
tracing::debug!("old `ok` content found, clearing cache");
} else {
tracing::warn!("unrecognized .cargo-ok content, clearing cache: {ok}");
}
// See comment of `unpack_package` about why removing all stuff.
paths::remove_dir_all(dst.as_path_unlocked())?;
}
},
Err(e) if e.kind() == io::ErrorKind::NotFound => {}
Err(e) => anyhow::bail!("unable to read .cargo-ok file at {path:?}: {e}"),
}
dst.create_dir()?;
let bytes_written = unpack(self.gctx, tarball, unpack_dir, &|_| true)?;
update_mtime_for_generated_files(unpack_dir);
// Now that we've finished unpacking, create and write to the lock file to indicate that
// unpacking was successful.
let mut ok = OpenOptions::new()
.create_new(true)
.read(true)
.write(true)
.open(&path)
.with_context(|| format!("failed to open `{}`", path.display()))?;
let lock_meta = LockMetadata { v: 1 };
write!(ok, "{}", serde_json::to_string(&lock_meta).unwrap())?;
View on GitHub (pinned to 98a09e7e7d)