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

replacements must specify a version to replace, but `{}` doe

Error message

replacements must specify a version to replace, but `{}` does not

What it means

Thrown by the `replace` function at src/workspace/parser/mod.rs:2136. A `[replace]` entry key must be a fully-qualified package spec of the form `name@version` (and that version must be a concrete version, not a requirement). After `PackageIdSpec::parse` succeeds, cargo checks `spec.version()`; if it is `None` (the key had no `@version` part) parsing bails.

Source

Thrown at src/workspace/parser/mod.rs:2136

                     version to replace, but `{}` does not",
                spec
            )
        })?;
        if spec.url().is_none() {
            spec.set_url(CRATES_IO_INDEX.parse().unwrap());
        }

        if replacement.is_version_specified() {
            bail!(
                "replacements cannot specify a version \
                     requirement, but found one for `{}`",
                spec
            );
        }

        let mut dep = dep_to_dependency(replacement, spec.name(), manifest_ctx, None)?;
        let version = spec.version().ok_or_else(|| {
            anyhow!(
                "replacements must specify a version \
                     to replace, but `{}` does not",
                spec
            )
        })?;
        unused_dep_keys(
            dep.name_in_toml().as_str(),
            "replace",
            replacement.unused_keys(),
            &mut manifest_ctx.warnings,
        );
        dep.set_version_req(OptVersionReq::exact(&version));
        replace.push((spec, dep));
    }
    Ok(replace)
}

fn patch(

View on GitHub (pinned to 0e07a15537)

Solutions

  1. Add the exact version to replace: `[replace] serde@1.0.197 = { git = "..." }`.
  2. Prefer `[patch]` for most modern use cases, which does not require pinning a version in the key.
  3. Ensure the version is concrete (e.g. `1.0.197`), not a requirement (`^1`).

Example fix

# before
[replace]
serde = { git = "https://..." }
# after
[replace]
serde@1.0.197 = { git = "https://..." }
Defensive patterns

Strategy: validation

Validate before calling

for (spec_key, _v) in replace_table {
    if !spec_key.contains('@') {
        return Err(format!("replace key {spec_key} must be name@version"));
    }
}

Prevention

When it happens

Trigger: A `[replace]` table with a key like `serde = { ... }` instead of `serde@1.0.197 = { ... }`. Reached when the spec parses but carries no version component.

Common situations: Confusing `[replace]` with `[patch]` (patch takes a bare name, replace needs `name@version`); copy-paste from outdated docs; forgetting the `@version` suffix.

Related errors


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