{"id":"32573c3e648ec587","repo":"rust-lang/cargo","slug":"local-registry-path-is-not-a-directory","errorCode":null,"errorMessage":"local registry path is not a directory: {}","messagePattern":"local registry path is not a directory: (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/sources/registry/local.rs","lineNumber":97,"sourceCode":"            src_path: gctx.registry_source_path().join(name),\n            index_path: Filesystem::new(root.join(\"index\")),\n            root: Filesystem::new(root.to_path_buf()),\n            gctx,\n            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    }","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/rust-lang/cargo/blob/0e07a155371a6ce88ae53a2c00df940280c09a67/src/sources/registry/local.rs#L79-L115","documentation":"A local (directory-based) registry's root path must be an existing directory. `LocalRegistry::update` (src/sources/registry/local.rs:96) checks `root.is_dir()` and bails if the configured root is missing, is a file, or is otherwise not a directory. Local registries are read directly from disk, so a non-directory root is fatal.","triggerScenarios":"Configuring `[source.<name>]` with `local-registry = \"path\"` where `path` doesn't exist or is a file; relative path resolved against an unexpected working directory; the registry directory was deleted/moved after being referenced.","commonSituations":"Vendoring-style setups pointing at a path that wasn't created; typo in the path; running cargo from a different directory than the config assumed (relative path); CI checkout missing the registry directory.","solutions":["Verify the path exists and is a directory: `ls -la <path>`; create or fix it if missing.","Use an absolute path in `.cargo/config.toml` to avoid working-directory ambiguity.","Ensure the directory follows the local-registry layout (an `index/` subdir and per-crate `.crate` files)."],"exampleFix":"# before\n[source.my-local]\nlocal-registry = \"vendor\"   # 'vendor' is a file or missing -> error\n\n# after: ensure it is an existing directory with the right layout\nmkdir -p vendor/index\n# (populate vendor/index and vendor/*.crate)\n[source.my-local]\nlocal-registry = \"/abs/path/to/vendor\"","handlingStrategy":"validation","validationCode":"// Validate local-registry root before handing it to Cargo.\nfn valid_local_registry_root(p: &Path) -> bool { p.is_dir() }","typeGuard":"pub fn is_local_registry_ready(p: &Path) -> bool {\n    p.is_dir() && p.join(\"index\").is_dir()\n}","tryCatchPattern":null,"preventionTips":["Use absolute paths for `local-registry` in config.","Verify the directory exists and has the expected layout before building."],"tags":["cargo","registry","local-registry","config","filesystem"],"analyzedSha":"0e07a155371a6ce88ae53a2c00df940280c09a67","analyzedAt":"2026-08-06T01:46:58.334Z","schemaVersion":2}