{"record":{"id":"7861add82028a269","repo":"rust-lang/cargo","slug":"path-is-not-a-blob-in-the-git-repo","errorCode":null,"errorMessage":"path `{}` is not a blob in the git repo","messagePattern":"path `(.+?)` is not a blob in the git repo","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/sources/registry/git_remote.rs","lineNumber":356,"sourceCode":"            registry: &GitRegistry<'_>,\n            path: &Path,\n            index_version: Option<&str>,\n        ) -> CargoResult<LoadResponse> {\n            let repo = registry.repo()?;\n            let repo = repo.as_ref().unwrap();\n            let tree = registry.tree()?;\n            let entry = tree.get_path(path);\n            let entry = entry?;\n            let git_file_hash = Some(entry.id().to_string());\n\n            // Check if the cache is valid.\n            if index_version.is_some() && index_version == git_file_hash.as_deref() {\n                return Ok(LoadResponse::CacheValid);\n            }\n\n            let object = entry.to_object(repo)?;\n            let Some(blob) = object.as_blob() else {\n                anyhow::bail!(\"path `{}` is not a blob in the git repo\", path.display())\n            };\n\n            Ok(LoadResponse::Data {\n                raw_data: blob.content().to_vec(),\n                index_version: git_file_hash,\n            })\n        }\n\n        loop {\n            return match load_helper(&self, path, index_version) {\n                Ok(result) => Ok(result),\n                Err(_) if !self.is_updated() => {\n                    // If git returns an error and we haven't updated the repo,\n                    // return pending to allow an update to try again.\n                    self.needs_update.set(true);\n                    self.update()?;\n                    continue;\n                }","sourceCodeStart":338,"sourceCodeEnd":374,"githubUrl":"https://github.com/rust-lang/cargo/blob/eb98b54bc9f3c74519f43d066cb3fd02ebc88df0/src/sources/registry/git_remote.rs#L338-L374","documentation":"When reading a file from a git-backed registry index, Cargo looked up the tree entry for `path`, retrieved the git object, but the object was not a blob (e.g. it was a tree, commit, or tag). The index format requires each crate's metadata to be stored as a blob file, so a non-blob indicates a corrupt or non-standard index repository.","triggerScenarios":"Inside `git_remote.rs` `load_helper`, after `tree.get_path(path)` resolves and `entry.to_object(repo)` succeeds, `object.as_blob()` returns `None`. Happens when the registry index git repo contains a directory (tree) or other object type where a blob is expected.","commonSituations":"Corrupted or hand-edited private registry index repository; an index repo where a crate path was replaced by a directory; partial clone/fetch that left an incomplete object; filesystem case-collision on case-insensitive volumes turning a file into a dir entry.","solutions":["Re-clone the registry index: remove `~/.cargo/registry/index/<name>` and run `cargo fetch`.","If you operate the private registry, inspect the index repo with `git ls-tree` and replace any non-blob entry at the offending path with a proper blob file.","Verify the registry index follows the crates.io index layout (one file per crate under the hashed prefix)."],"exampleFix":"# inspect the offending object in a private index\n$ git --git-dir ~/.cargo/registry/git/index ls-tree HEAD <path>\n# if it shows `tree` instead of `blob`, fix the upstream index, then:\n$ rm -rf ~/.cargo/registry/index/<name> && cargo fetch","handlingStrategy":"try-catch","validationCode":"// Validate the index object type before assuming blob.\nfn assert_blob(repo: &git2::Repository, tree: &git2::Tree, path: &Path) -> Result<(), anyhow::Error> {\n    let entry = tree.get_path(path)?;\n    let obj = entry.to_object(repo)?;\n    if obj.as_blob().is_none() {\n        anyhow::bail!(\"not a blob: {}\", path.display());\n    }\n    Ok(())\n}","typeGuard":"fn is_blob(repo: &git2::Repository, tree: &git2::Tree, path: &std::path::Path) -> bool {\n    tree.get_path(path).ok()\n        .and_then(|e| e.to_object(repo).ok())\n        .map_or(false, |o| o.as_blob().is_some())\n}","tryCatchPattern":"match load_helper(self, path, index_version) {\n    Ok(r) => Ok(r),\n    Err(e) if e.to_string().contains(\"not a blob\") => { /* re-clone index */ reclone_index()?; load_helper(self, path, index_version) }\n    Err(e) => Err(e),\n}","preventionTips":["Operate private registry indices following the crates.io layout (blobs only).","Periodically `git fsck` the index repo.","Treat non-blob entries as a corrupt-index signal and re-clone."],"tags":["cargo","registry","git-index","blob","integrity","configuration"],"backgroundTag":null,"analyzedSha":"eb98b54bc9f3c74519f43d066cb3fd02ebc88df0","analyzedAt":"2026-08-11T17:42:36.556Z","contentChangedAt":"2026-08-11T17:42:36.556Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}