{"id":"63d2bdb080b77e1c","repo":"rust-lang/cargo","slug":"local-registry-index-path-is-not-a-directory","errorCode":null,"errorMessage":"local registry index path is not a directory: {}","messagePattern":"local registry index path is not a directory: (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/sources/registry/local.rs","lineNumber":101,"sourceCode":"            updated: Cell::new(false),\n            quiet: false,\n        }\n    }\n\n    fn update(&self) -> CargoResult<()> {\n        if self.updated.get() {\n            return Ok(());\n        }\n        // Nothing to update, we just use what's on disk. Verify it actually\n        // exists though. We don't use any locks as we're just checking whether\n        // these directories exist.\n        let root = self.root.clone().into_path_unlocked();\n        if !root.is_dir() {\n            anyhow::bail!(\"local registry path is not a directory: {}\", root.display());\n        }\n        let index_path = self.index_path.clone().into_path_unlocked();\n        if !index_path.is_dir() {\n            anyhow::bail!(\n                \"local registry index path is not a directory: {}\",\n                index_path.display()\n            );\n        }\n        self.updated.set(true);\n        Ok(())\n    }\n}\n\n#[async_trait::async_trait(?Send)]\nimpl<'gctx> RegistryData for LocalRegistry<'gctx> {\n    fn prepare(&self) -> CargoResult<()> {\n        Ok(())\n    }\n\n    fn index_path(&self) -> &Filesystem {\n        &self.index_path\n    }","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/rust-lang/cargo/blob/0e07a155371a6ce88ae53a2c00df940280c09a67/src/sources/registry/local.rs#L83-L119","documentation":"Even when a local registry root exists, Cargo additionally requires an `index/` subdirectory inside it (src/sources/registry/local.rs:100). If `root/index` is missing or is not a directory, it bails. The index directory is where Cargo reads the JSON-line metadata for each crate.","triggerScenarios":"A local-registry root that exists but lacks the `index/` subdir; `index` exists but is a regular file; a partially-set-up vendor directory.","commonSituations":"Hand-creating a local registry without the index; a vendoring tool that wrote `.crate` files but not the index; renaming/moving the index directory; typo in the layout.","solutions":["Confirm `root/index` exists and is a directory; create it and populate it with the proper JSON-line index files if missing.","Regenerate the local registry with a tool that produces the correct layout (e.g. `cargo vendor` for vendored sources, or the documented local-registry format).","Check that nothing (a build step, `.gitignore`) deleted the index directory."],"exampleFix":"# before: root exists but index/ missing\nmy-registry/\n  foo-1.0.0.crate\n\n# after\nmy-registry/\n  index/\n    fo/o/foo   # JSON-line index entry\n  foo-1.0.0.crate","handlingStrategy":"validation","validationCode":"// Check both root and index/ exist as directories.\nfn valid_local_registry(p: &Path) -> bool {\n    p.is_dir() && p.join(\"index\").is_dir()\n}","typeGuard":"pub fn is_local_registry_ready(p: &Path) -> bool {\n    p.is_dir() && p.join(\"index\").is_dir()\n}","tryCatchPattern":null,"preventionTips":["Generate local registries with a tool that produces the documented layout (`index/` subdir + `.crate` files).","Add a CI check that asserts the local-registry directory structure before invoking cargo."],"tags":["cargo","registry","local-registry","config","filesystem"],"analyzedSha":"0e07a155371a6ce88ae53a2c00df940280c09a67","analyzedAt":"2026-08-06T01:46:58.334Z","schemaVersion":2}