rust-lang/cargo · error · anyhow::Error
invalid url `{}`: cannot-be-a-base-URLs are not supported
Error message
invalid url `{}`: cannot-be-a-base-URLs are not supported What it means
CanonicalUrl::new normalizes registry/git URLs for internal comparison and hashing, and it refuses URLs where url::Url::cannot_be_a_base() is true. Such URLs lack a hierarchical base (no scheme separator producing a path) — classic examples are SCP-style `host:path` strings like `github.com:rust-lang/rustfmt.git` or `git@github.com:owner/repo.git`. Cargo cannot apply its path-stripping/canonicalization logic to them, so it bails.
Source
Thrown at src/util/canonical_url.rs:25
///
/// A "canonical" url is only intended for internal comparison purposes in
/// Cargo. It's to help paper over mistakes such as depending on
/// `github.com/foo/bar` vs `github.com/foo/bar.git`. This is **only** for
/// internal purposes within Cargo and provides no means to actually read the
/// underlying string value of the `Url` it contains. This is intentional,
/// because all fetching should still happen within the context of the original
/// URL.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct CanonicalUrl(Url);
impl CanonicalUrl {
pub fn new(url: &Url) -> CargoResult<CanonicalUrl> {
let mut url = url.clone();
// cannot-be-a-base-urls (e.g., `github.com:rust-lang/rustfmt.git`)
// are not supported.
if url.cannot_be_a_base() {
anyhow::bail!(
"invalid url `{}`: cannot-be-a-base-URLs are not supported",
url
)
}
// Strip a trailing slash.
if url.path().ends_with('/') {
url.path_segments_mut().unwrap().pop_if_empty();
}
// Perform further canonicalization specific to git registries, which
// do not contain a `+` specifier.
if !url.scheme().contains('+') {
// For GitHub URLs specifically, just lower-case everything. GitHub
// treats both the same, but they hash differently, and we're gonna be
// hashing them. This wants a more general solution, and also we're
// almost certainly not using the same case conversion rules that GitHub
// does. (See issue #84)View on GitHub (pinned to 0e07a15537)
Solutions
- Prefix the URL with a proper scheme: use `ssh://git@github.com/owner/repo.git` instead of `git@github.com:owner/repo.git`.
- For GitHub dependencies prefer `https://github.com/owner/repo.git`.
- If using a registry index URL, ensure it begins with `https://` or `sparse+https://`.
- Validate the URL parses with a scheme and a non-empty host before passing it to Cargo APIs.
Example fix
# Cargo.toml before git = "git@github.com:owner/repo.git" # after git = "ssh://git@github.com/owner/repo.git" # or simpler https = "https://github.com/owner/repo.git"
Defensive patterns
Strategy: validation
Validate before calling
use url::Url;
fn is_cargo_safe_url(s: &str) -> Result<(), String> {
let u = Url::parse(s).map_err(|e| format!("not a URL: {e}"))?;
if u.cannot_be_a_base() {
return Err(format!("{s} is a cannot-be-a-base URL; add a scheme like https:// or ssh://"));
}
Ok(())
}
// call before constructing a git dependency / registry index URL Type guard
fn is_valid_canonical_url(s: &str) -> bool {
Url::parse(s).map(|u| !u.cannot_be_a_base()).unwrap_or(false)
} Try / catch
match CanonicalUrl::new(&url) {
Ok(c) => use c,
Err(e) if e.to_string().contains("cannot-be-a-base") => {
return Err(anyhow!("rewrite the URL with a scheme, e.g. ssh://{url}"));
}
Err(e) => return Err(e),
} Prevention
- Always include a scheme (https://, ssh://, git://) on git/registry URLs in Cargo.toml.
- Prefer HTTPS GitHub URLs to avoid SCP-notation confusion.
- Lint manifests for URLs lacking `://`.
When it happens
Trigger: Constructing a git dependency or registry source whose URL parses as cannot-be-a-base: passing an SCP-notation string (`host:path`) directly as a registry index URL or as a git dependency URL in Cargo.toml, or feeding such a Url into CanonicalUrl::new programmatically.
Common situations: Copying a GitHub SSH clone command's `git@github.com:owner/repo.git` argument into a Cargo.toml git dependency; using a registry index URL without an `https://`/`ssh://`/`git://` scheme; hand-building a url::Url from a bare `host:path` string.
Related errors
- invalid package name: `{url}` Use `cargo install --git {
- no path segments on url
- couldn't find username
- couldn't find repository name
- too many segments on URL
AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06).
Data as JSON: /data/errors/b879c09b0b4540cd.json.
Report an issue: GitHub.