rust-lang/cargo · error · anyhow::Error

`{}` was defined in {} but could not be resolved with {}

Error message

`{}` was defined in {} but could not be resolved with {}

What it means

Returned by `resolve_relative_path` (src/workspace/registry.rs is wrong — actual: src/workspace/workspace.rs:2142) when `diff_paths(joined_path, new_root)` returns `None`, meaning the path formed by joining `old_root` + `rel_path` does not lie underneath `new_root`. Cargo cannot express a relative path between the two trees, so it errors naming the label, where it was defined, and the target root it failed to resolve against.

Source

Thrown at src/workspace/workspace.rs:2142

                        "ignoring `registries.{name}.min-publish-age` without `-Zmin-publish-age`"
                    ))?;
                }
            }
        }
    }

    Ok(())
}

pub fn resolve_relative_path(
    label: &str,
    old_root: &Path,
    new_root: &Path,
    rel_path: &str,
) -> CargoResult<String> {
    let joined_path = normalize_path(&old_root.join(rel_path));
    match diff_paths(joined_path, new_root) {
        None => Err(anyhow!(
            "`{}` was defined in {} but could not be resolved with {}",
            label,
            old_root.display(),
            new_root.display()
        )),
        Some(path) => Ok(path
            .to_str()
            .ok_or_else(|| {
                anyhow!(
                    "`{}` resolved to non-UTF value (`{}`)",
                    label,
                    path.display()
                )
            })?
            .to_owned()),
    }
}

View on GitHub (pinned to 0e07a15537)

Solutions

  1. Verify `rel_path` (with `..`) still resolves under `new_root` after the move; adjust the manifest path to point inside the new root.
  2. Ensure `old_root` and `new_root` are both absolute and canonicalized before calling.
  3. If the path legitimately lives outside the new root, switch the manifest to an absolute path or a registry/git dependency instead of a relative one.

Example fix

// before
let p = resolve_relative_path("dep", &old_root, &new_root, "../../outside/dep")?;
// after — move dep under new_root and reference relatively
let p = resolve_relative_path("dep", &old_root, &new_root, "members/dep")?;
Defensive patterns

Strategy: validation

Validate before calling

use std::path::{Path, Component};
fn is_under(new_root: &Path, joined: &Path) -> bool {
    let joined = std::fs::canonicalize(joined).unwrap_or_else(|_| joined.to_path_buf());
    let new_root = std::fs::canonicalize(new_root).unwrap_or_else(|_| new_root.to_path_buf());
    joined.starts_with(new_root)
}
// before calling resolve_relative_path, assert is_under(&new_root, &old_root.join(rel_path))

Try / catch

// best-effort: fall back to an absolute path string
let p = resolve_relative_path(label, &old_root, &new_root, rel)
    .unwrap_or_else(|_| old_root.join(rel).to_string_lossy().into_owned());

Prevention

When it happens

Trigger: Calling `resolve_relative_path(label, old_root, new_root, rel_path)` where `old_root.join(rel_path)` canonicalizes outside of `new_root` — e.g. the relative path escapes via `..` components, or `new_root` is not an ancestor of the joined path.

Common situations: Workspace relocation where a patch/path dependency referenced by a relative `..` no longer sits under the new workspace root; publishing or packaging with a rewritten root; symlinks causing `diff_paths` to disagree about ancestry.

Related errors


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