{"record":{"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":"exception","errorClass":null,"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/eb98b54bc9f3c74519f43d066cb3fd02ebc88df0/src/sources/registry/local.rs#L79-L115","documentation":"A local registry (`registry = \"file://...\"` style source) requires its root directory to exist on disk. During `update()`, Cargo checks `root.is_dir()`; if the path is missing or is a file, it bails. Local registries serve pre-populated index + `.crate` files from the filesystem (no network), so the directory must exist.","triggerScenarios":"A `[source.<name>]` or dependency configured with `registry =` pointing at a local filesystem path that does not exist or is not a directory. Reached on the first `update()` of a `LocalRegistry`.","commonSituations":"Path moved/renamed since config was written; relative path interpreted from a different working directory; local registry never vendored into place; typo in the `file://` URL; build server missing the mounted registry volume.","solutions":["Verify the path exists and is a directory: `ls -la <path>`.","Fix the configured path in `.cargo/config.toml` / `Cargo.toml` to the correct absolute location.","Populate the local registry (vendor the index and `.crate` files) before building.","Use an absolute path to avoid working-directory ambiguity."],"exampleFix":"# before\n[source.mylocal]\nregistry = \"file:///opt/cargo-registry\"   # missing\n\n# after\n[source.mylocal]\nregistry = \"file:///srv/cargo-registry\"   # exists and is a dir","handlingStrategy":"validation","validationCode":"fn ensure_local_registry_root(root: &Path) -> Result<(), anyhow::Error> {\n    if !root.is_dir() { anyhow::bail!(\"local registry root is not a directory: {}\", root.display()); }\n    Ok(())\n}","typeGuard":"fn local_registry_root_exists(root: &std::path::Path) -> bool { root.is_dir() }","tryCatchPattern":"if !root.is_dir() {\n    // attempt to mount/populate, else surface actionable message\n    return Err(anyhow!(\"local registry path missing: {}; vendor or fix config\", root.display()));\n}","preventionTips":["Use absolute paths for local registries.","Vendor the registry before building (`cargo vendor`).","CI: verify the local registry path is mounted before `cargo build`.","Lint config for moved/non-existent local registry paths."],"tags":["cargo","registry","local","filesystem","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"}