rust-lang/cargo · error · anyhow::Error
unknown vcs specification
Error message
unknown vcs specification: `{}` What it means
This error is raised when a `VersionControl` value cannot be parsed from a string via its `FromStr` implementation (used during config deserialization). The string must exactly match one of the supported VCS names: `git`, `hg`, `pijul`, `fossil`, or `none`. Any other value (including typos, capitalization differences, or empty strings) aborts with `unknown vcs specification: \`<input>\``.
Solutions
- Open the config file and change the `vcs` value to one of exactly: `git`, `hg`, `pijul`, `fossil`, or `none` (lowercase, no whitespace).
- If a template/variable was supposed to be substituted (message shows a literal `{}`), fix the templating/substitution step so a real VCS name is written.
- Check the docs for the config schema to confirm which VCS aliases are supported; there are none beyond the five listed — e.g. `mercurial` is not accepted, use `hg`.
- If you need a new VCS supported, this is upstream code (src/context/schema.rs `from_str`); file/patch the library to add the match arm.
Example fix
// before (config) vcs = "mercurial" // after (config) vcs = "hg"
Defensive patterns
Strategy: validation
Validate before calling
const VALID_VCS: &[&str] = &["git", "hg", "pijul", "fossil", "none"];
fn is_valid_vcs(s: &str) -> bool {
VALID_VCS.contains(&s.trim())
}
// before deserializing config:
assert!(is_valid_vcs(cfg.vcs.as_str()), "unsupported vcs: {}", cfg.vcs); Type guard
fn is_known_vcs(s: &str) -> Option<VersionControl> {
match s.trim() {
"git" => Some(VersionControl::Git),
"hg" => Some(VersionControl::Hg),
"pijul" => Some(VersionControl::Pijul),
"fossil" => Some(VersionControl::Fossil),
"none" => Some(VersionControl::NoVcs),
_ => None,
}
} Try / catch
match VersionControl::from_str(raw) {
Ok(vcs) => /* proceed */,
Err(e) => eprintln!("config error: {e}; expected one of git, hg, pijul, fossil, none"),
} Prevention
- Validate the `vcs` field against the allowed list before deserializing or at config-load time with a clear error message.
- Never write templated placeholders directly into config; assert substitution completed (reject values containing `{`).
- Use the library's own `VersionControl` enum in tooling instead of raw strings so invalid values fail at compile time.
- Keep values lowercase and trimmed; there are no aliases (e.g. `mercurial` -> `hg`).
When it happens
Trigger: Deserializing a config (e.g. cargo/alternative-registry style config) whose `vcs` key (or equivalent field of type `VersionControl`) contains a value other than the five recognized strings, e.g. `vcs = "Git"` (capitalized), `vcs = "mercurial"`, or a variable left unexpanded like the literal `{}` shown in the message when formatting substitutes the offending input.
Common situations: Typing `vcs = "git"` with stray whitespace or wrong case; using a full VCS name like `mercurial` or `subversion` instead of `hg`; templated config where a placeholder was not substituted (message shows a literal `{}`); migrating configs from tools that accept different VCS names.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- unknown vcs specification
- artifact-dir was not locked during clean
- can't find library ` `, rename file to `src/lib.rs` or…
- cannot mix `proc-macro` crate type with others
- cannot specify both `metabuild` and `build`
AI-assisted analysis of rust-lang/cargo@98a09e7e7d (2026-09-16).
Data as JSON: /api/errors/7cfabaa870875f33.
Report an issue: GitHub.
Appendix: source
Thrown at src/context/schema.rs:114
VersionControl::Hg => "hg",
VersionControl::Pijul => "pijul",
VersionControl::Fossil => "fossil",
VersionControl::NoVcs => "none",
}
}
}
impl FromStr for VersionControl {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, anyhow::Error> {
match s {
"git" => Ok(VersionControl::Git),
"hg" => Ok(VersionControl::Hg),
"pijul" => Ok(VersionControl::Pijul),
"fossil" => Ok(VersionControl::Fossil),
"none" => Ok(VersionControl::NoVcs),
other => anyhow::bail!("unknown vcs specification: `{}`", other),
}
}
}
impl<'de> de::Deserialize<'de> for VersionControl {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
FromStr::from_str(&s).map_err(de::Error::custom)
}
}
/// Definition of a source in a config file.
#[derive(Debug, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub struct SourceConfigDef {View on GitHub (pinned to 98a09e7e7d)