rust-lang/cargo · warning

package replacement is not used

Error message

package replacement is not used: {}

What it means

During workspace resolution, Cargo checks each `[replace]` entry from the workspace root against the resolved graph: if no resolved package matches the replace spec while failing the dependency's match mode, the replacement never applies. Rather than erroring, resolve_ws_with_opts emits this warning to tell the developer the replace rule is dead configuration.

Solutions

  1. Review the named replace spec in the workspace root Cargo.toml and correct the package name/version so it matches a package actually in the dependency graph.
  2. Remove the unused [replace] entry, or migrate to [patch] which is the modern mechanism for overriding sources.
  3. Run `cargo tree -i <spec>` (or inspect Cargo.lock) to confirm what the spec should match.

Example fix

// before: Cargo.toml
[replace]
"serde:1.0.0" = { path = "../serde" }

// after: Cargo.toml (matches resolved serde 1.0.2)
[replace]
"serde:1.0.2" = { path = "../serde" }
Defensive patterns

Strategy: validation

Validate before calling

# confirm each [replace] spec actually matches a locked package
for spec in $(awk '/^"/ {print $1}' Cargo.toml | tr -d '"'); do
  grep -q "${spec%%:*}" Cargo.lock || echo "replace spec '$spec' matches nothing"
done

Try / catch

// the warning is non-fatal; capture shell output and flag it
if stderr.contains("package replacement is not used:") {
    // treat as dead config: alert or fail CI lint step
}

Prevention

When it happens

Trigger: Calling resolve_ws_with_opts on a workspace whose root manifest declares a [replace] section (e.g. replace "with" = { path = "..." }) where the spec string matches a resolved package only via the dependency's looser match mode, or matches nothing at all — commonly because the spec's version doesn't match what actually resolved.

Common situations: Pinned replace specs whose versions drifted after a lockfile update; replaced crate names spelled differently from the resolved package; legacy [replace] usage that modern dependency resolution no longer engages; migration to [patch] leaving stale entries.

Related errors


AI-assisted analysis of rust-lang/cargo@98a09e7e7d (2026-09-22). Data as JSON: /api/errors/ecff6b503aa6e5bc. Report an issue: GitHub.

Appendix: source

Thrown at src/ops/resolve.rs:186

    let (resolve, resolved_with_overrides) = if ws.require_optional_deps() {
        // First, resolve the root_package's *listed* dependencies, as well as
        // downloading and updating all remotes and such.
        let resolve = resolve_with_registry(ws, &mut registry, dry_run)?;
        // No need to add patches again, `resolve_with_registry` has done it.
        let add_patches = false;

        // Second, resolve with precisely what we're doing. Filter out
        // transitive dependencies if necessary, specify features, handle
        // overrides, etc.
        add_overrides(&mut registry, ws)?;

        for (replace_spec, dep) in ws.root_replace() {
            if !resolve.iter().any(|r| {
                replace_spec.matches(r) && !dep.matches_id(r, VersionReqMatchMode::Default)
            }) {
                ws.gctx()
                    .shell()
                    .warn(format!("package replacement is not used: {}", replace_spec))?
            }

            let mut unused_fields = Vec::new();
            if dep.features().len() != 0 {
                unused_fields.push("`features`");
            }
            if !dep.uses_default_features() {
                unused_fields.push("`default-features`")
            }
            if !unused_fields.is_empty() {
                ws.gctx().shell().print_report(
                    &[Level::WARNING
                        .secondary_title(format!(
                            "unused field in replacement for `{}`: {}",
                            dep.package_name(),
                            unused_fields.join(", ")
                        ))
                        .element(Level::NOTE.message(format!(

View on GitHub (pinned to 98a09e7e7d)