{"record":{"id":"ea6580d267e3b020","repo":"rust-lang/cargo","slug":"unable-to-read-cargo-ok-file-at-path-e","errorCode":null,"errorMessage":"unable to read .cargo-ok file at {path:?}: {e}","messagePattern":"unable to read \\.cargo-ok file at (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/sources/registry/mod.rs","lineNumber":586,"sourceCode":"                        .mark_registry_src_used(global_cache_tracker::RegistrySrc {\n                            encoded_registry_name: self.name,\n                            package_dir: package_dir.into(),\n                            size: None,\n                        });\n                    return Ok(unpack_dir.to_path_buf());\n                }\n                _ => {\n                    if ok == \"ok\" {\n                        tracing::debug!(\"old `ok` content found, clearing cache\");\n                    } else {\n                        tracing::warn!(\"unrecognized .cargo-ok content, clearing cache: {ok}\");\n                    }\n                    // See comment of `unpack_package` about why removing all stuff.\n                    paths::remove_dir_all(dst.as_path_unlocked())?;\n                }\n            },\n            Err(e) if e.kind() == io::ErrorKind::NotFound => {}\n            Err(e) => anyhow::bail!(\"unable to read .cargo-ok file at {path:?}: {e}\"),\n        }\n        dst.create_dir()?;\n\n        let bytes_written = unpack(self.gctx, tarball, unpack_dir, &|_| true)?;\n        update_mtime_for_generated_files(unpack_dir);\n\n        // Now that we've finished unpacking, create and write to the lock file to indicate that\n        // unpacking was successful.\n        let mut ok = OpenOptions::new()\n            .create_new(true)\n            .read(true)\n            .write(true)\n            .open(&path)\n            .with_context(|| format!(\"failed to open `{}`\", path.display()))?;\n\n        let lock_meta = LockMetadata { v: 1 };\n        write!(ok, \"{}\", serde_json::to_string(&lock_meta).unwrap())?;\n","sourceCodeStart":568,"sourceCodeEnd":604,"githubUrl":"https://github.com/rust-lang/cargo/blob/98a09e7e7d62850f14e5b6132101fc1edd19a16f/src/sources/registry/mod.rs#L568-L604","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before: permission-denied / corrupt .cargo-ok\n$ cargo build\nerror: unable to read .cargo-ok file at \".../.cargo-ok\": Permission denied\n\n# after\n$ chmod -R u+rwX ~/.cargo/registry/src\n$ rm -rf ~/.cargo/registry/src/<index>/<pkg>-<ver>\n$ cargo build","handlingStrategy":"try-catch","validationCode":"fn can_read_ok_file(path: &Path) -> bool {\n    match std::fs::read_to_string(path) {\n    Ok(_) => true,\n    Err(e) if e.kind() == std::io::ErrorKind::NotFound => true,\n    Err(_) => false,\n    }\n}","typeGuard":"fn ok_file_accessible(path: &std::path::Path) -> bool {\n    std::fs::metadata(path).map_or(true, |_| std::fs::read_to_string(path).is_ok())\n}","tryCatchPattern":"match fs::read_to_string(&path) {\n    Ok(s) => /* parse */,\n    Err(e) if e.kind() == io::ErrorKind::NotFound => {},\n    Err(e) => {\n        // attempt recovery: fix perms or wipe the unpack dir, then retry once\n        let _ = fs::remove_dir_all(dst.as_path_unlocked());\n        return unpack(...);\n    }\n}","preventionTips":["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."],"tags":["cargo","registry","unpack","io","permissions","filesystem"],"backgroundTag":null,"analyzedSha":"98a09e7e7d62850f14e5b6132101fc1edd19a16f","analyzedAt":"2026-08-11T17:42:36.556Z","contentChangedAt":"2026-08-11T17:42:36.556Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}