rust-lang/cargo · error

local path

Error message

local path

What it means

In `cargo vendor`, for a `SourceKind::LocalRegistry` the code converts the source URL to a filesystem path via `sid.url().to_file_path().expect("local path")`. `Url::to_file_path` returns `Err` when the URL scheme is not `file://` or the host component is non-empty (e.g. a `file://host/...` URL).

Source

Thrown at src/ops/cargo_vendor.rs:252

        )?;

        let _ = fs::remove_dir_all(&dst);

        let mut file_cksums = BTreeMap::new();

        // Need this mapping anyway because we will directly consult registry sources,
        // otherwise builtin source replacement (sparse registry) won't be respected.
        let sid = source_replacement_cache.get(id.source_id())?;

        if sid.is_registry() {
            // To keep the unpacked source from registry in a pristine state,
            // we'll do a direct extraction into the vendor directory.
            let registry = match sid.kind() {
                SourceKind::Registry | SourceKind::SparseRegistry => {
                    RegistrySource::remote(sid, gctx)?
                }
                SourceKind::LocalRegistry => {
                    let path = sid.url().to_file_path().expect("local path");
                    RegistrySource::local(sid, &path, gctx)
                }
                _ => unreachable!("not registry source: {sid}"),
            };

            let walkdir = |root| {
                WalkDir::new(root)
                    .into_iter()
                    // It is safe to skip errors,
                    // since we'll hit them during copying/reading later anyway.
                    .filter_map(|e| e.ok())
                    // There should be no symlink in tarballs on crates.io,
                    // but might be wrong for local registries.
                    // Hence here be conservative and include symlinks.
                    .filter(|e| e.file_type().is_file() || e.file_type().is_symlink())
            };
            let mut compute_file_cksums = |root| {
                for e in walkdir(root) {

View on GitHub (pinned to 0e07a15537)

Solutions

  1. Inspect your `.cargo/config.toml` `[source]` / `[registry]` entries and confirm the local-registry URL is a plain `file:///absolute/path` (no host).
  2. Re-point the source to a directory path directly (`registry = "file:///path/to/registry"`) and re-run `cargo vendor`.
  3. On Windows, ensure drive letters are encoded as `file:///C:/...` not `file://C:/...`.
  4. If the URL looks correct, report a cargo bug with the exact `[source]` block.

Example fix

// before
let path = sid.url().to_file_path().expect("local path");

// after
let path = sid.url().to_file_path()
    .map_err(|_| anyhow::format_err!(
        "local registry source `{}` is not a valid file:// path", sid.url()))?;
Defensive patterns

Strategy: validation

Validate before calling

// Validate local-registry source URLs are bare file:// paths before vendoring.
if !url.as_str().starts_with("file:///") || url.host_str().is_some() {
    return Err(anyhow!("local registry URL must be file:///abs/path with no host: {}", url));
}

Prevention

When it happens

Trigger: Vendoring a dependency that resolves to a local-registry source whose `url` is configured as something other than a bare `file://` path — e.g. a `file://localhost/...` URL with a host, or accidentally a `sparse+file://`, `https://`, or relative path string.

Common situations: A `[source]` replacement mapping a registry to a local registry path that was written with a host component or wrong scheme; migrating a local-registry config between Windows (`file:///C:/...`) and Unix; typos in `replace-with`/`local-registry` config.

Related errors


AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06). Data as JSON: /data/errors/adb69f3dc4052fbc.json. Report an issue: GitHub.