{"record":{"id":"da80fdfc03aabfc6","repo":"rust-lang/cargo","slug":"replacements-must-specify-a-version-to-replace-bu","errorCode":null,"errorMessage":"replacements must specify a version to replace, but `{}` does not","messagePattern":"replacements must specify a version to replace, but `(.+?)` does not","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/workspace/parser/mod.rs","lineNumber":2161,"sourceCode":"                     version to replace, but `{}` does not\",\n                spec\n            )\n        })?;\n        if spec.url().is_none() {\n            spec.set_url(CRATES_IO_INDEX.parse().unwrap());\n        }\n\n        if replacement.is_version_specified() {\n            bail!(\n                \"replacements cannot specify a version \\\n                     requirement, but found one for `{}`\",\n                spec\n            );\n        }\n\n        let mut dep = dep_to_dependency(replacement, spec.name(), manifest_ctx, None)?;\n        let version = spec.version().ok_or_else(|| {\n            anyhow!(\n                \"replacements must specify a version \\\n                     to replace, but `{}` does not\",\n                spec\n            )\n        })?;\n        unused_dep_keys(\n            dep.name_in_toml().as_str(),\n            \"replace\",\n            replacement.unused_keys(),\n            &mut manifest_ctx.warnings,\n        );\n        dep.set_version_req(OptVersionReq::exact(&version));\n        replace.push((spec, dep));\n    }\n    Ok(replace)\n}\n\nfn patch(","sourceCodeStart":2143,"sourceCodeEnd":2179,"githubUrl":"https://github.com/rust-lang/cargo/blob/98a09e7e7d62850f14e5b6132101fc1edd19a16f/src/workspace/parser/mod.rs#L2143-L2179","documentation":"Thrown in the [replace] section parser when a PackageIdSpec used as a replacement key lacks a version. Replacements must pin the exact version to replace (e.g. 'my-crate:1.0.0'), so spec.version() returning None is fatal. The spec string is interpolated. This is separate from the check that disallows a version *requirement* inside the replacement dependency itself.","triggerScenarios":"Writing [replace.\"my-crate\"] without a version qualifier in Cargo.toml. PackageIdSpec::parse succeeds (it accepts a bare name) but spec.version() is None, hitting the ok_or_else.","commonSituations":"A developer uses [replace] for the first time and omits the version. Confusing [patch] (which takes a URL key) with [replace] (which takes a name:version key). Stale documentation showing replace syntax without a version.","solutions":["Add the version to the replace key: [replace.\"my-crate:1.0.0\"].","Consider migrating to [patch] which is the modern, recommended replacement mechanism.","Verify the version matches the one you want to override exactly (replace pins, it does not range)."],"exampleFix":"# before\n[replace]\n\"my-crate\" = { path = \"../my-crate\" }\n\n# after\n[replace]\n\"my-crate:1.0.0\" = { path = \"../my-crate\" }","handlingStrategy":"validation","validationCode":"fn replace_key_has_version(key: &str) -> Result<(), String> {\n    // PackageIdSpec keys must be name:version\n    if !key.contains(':') {\n        return Err(format!(\"replace key `{key}` must include a version, e.g. `{key}:1.0.0`\"));\n    }\n    Ok(())\n}","typeGuard":"fn replace_key_is_versioned(key: &str) -> bool {\n    key.split(':').count() == 2 && key.split(':').nth(1).map(|v| !v.is_empty()).unwrap_or(false)\n}","tryCatchPattern":null,"preventionTips":["Always include the exact version in [replace] keys: \"name:version\".","Prefer [patch] over [replace] for modern manifests.","Review replace syntax against current cargo docs before use."],"tags":["cargo","replace","manifest","version","parser"],"backgroundTag":null,"analyzedSha":"98a09e7e7d62850f14e5b6132101fc1edd19a16f","analyzedAt":"2026-08-11T17:42:36.556Z","contentChangedAt":"2026-08-11T17:42:36.556Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}