denoland/deno · error · AnyError
Registry API URL cannot be used as a base URL
Error message
Registry API URL cannot be used as a base URL
What it means
Denos registry client builds JSR API endpoint URLs by appending path segments (scopes/packages/versions/...) to a configured registry API base URL via `url.path_segments_mut()` in append_path_segments (cli/registry.rs:183). The `url` crate returns Err from path_segments_mut for URLs that cannot have path segments — notably URLs whose path is not slash-based, such as `cannot-be-a-base` URLs (e.g. `data:`, `mailto:`, or a custom scheme without an authority/path). When that happens the library aborts with this error instead of building a malformed request URL.
Source
Thrown at cli/registry.rs:193
package,
"versions",
version,
"provenance",
],
)
}
fn append_path_segments(
base_url: &Url,
segments: &[&str],
) -> Result<Url, AnyError> {
let mut url = base_url.clone();
url.set_query(None);
url.set_fragment(None);
url
.path_segments_mut()
.map_err(|_| {
deno_core::anyhow::anyhow!(
"Registry API URL cannot be used as a base URL"
)
})?
.pop_if_empty()
.extend(segments);
Ok(url)
}
pub async fn get_package(
client: &HttpClient,
registry_api_url: &Url,
scope: &str,
package: &str,
authorization: Option<&str>,
) -> Result<http::Response<deno_fetch::ResBody>, AnyError> {
let package_url = get_package_api_url(registry_api_url, scope, package)?;
let mut request = client.get(package_url)?;
// The registry responds with a 404 for private packages unless the requestView on GitHub (pinned to f7822238ca)
Solutions
- Fix the configured registry API URL to a normal hierarchical URL with a scheme, host and path, e.g. `https://jsr.io` (default) or your proxy's `https://registry.example.com/api`.
- Check deno.json / deno.jsonc `scopes`/registry endpoint configuration and any DENO_* env vars for a malformed or non-HTTP(S) URL value.
- If constructing the URL programmatically (tests, tooling), use `Url::parse("https://...")` rather than hand-built or `data:` URLs.
- If behind a custom gateway, ensure it preserves a normal path structure (`https://host/base/`) so path segments can be appended.
Example fix
// before (deno.json - cannot-be-a-base URL)
{
"scopes": {
"jsr": { "endpoints": { "api": "data:internal-registry" } }
}
}
// after
{
"scopes": {
"jsr": { "endpoints": { "api": "https://registry.internal.example.com/api" } }
}
} Defensive patterns
Strategy: validation
Validate before calling
use url::Url;
fn validate_registry_api_url(raw: &str) -> Result<Url, String> {
let url = Url::parse(raw).map_err(|e| format!("invalid URL: {e}"))?;
if !matches!(url.scheme(), "http" | "https") {
return Err(format!("registry API URL must be http(s), got scheme '{}'", url.scheme()));
}
if url.cannot_be_a_base() {
return Err("registry API URL cannot be a base URL (no hierarchical path)".into());
}
if url.host_str().is_none() {
return Err("registry API URL must include a host".into());
}
Ok(url)
} Type guard
fn is_valid_base_url(url: &Url) -> bool {
!url.cannot_be_a_base()
&& matches!(url.scheme(), "http" | "https")
&& url.host_str().is_some()
} Try / catch
match validate_registry_api_url(&raw_url) {
Ok(url) => registry::get_package(&client, &url, scope, package, auth).await,
Err(e) => {
eprintln!("Cannot talk to JSR registry: {e}");
std::process::exit(1);
}
} Prevention
- Always use an absolute http(s) URL (e.g. https://jsr.io) for the registry API endpoint in deno.json or env.
- Never paste non-hierarchical URLs (data:, mailto:, bare hostnames) into registry configuration.
- Validate the URL parses with Url::parse and has a host before storing it in config.
- When mocking in tests, use `Url::parse("https://jsr.test/")` rather than placeholder schemes.
When it happens
Trigger: Calling get_package, get_package_version, or get_package_version_provenance (which all route through append_path_segments) with a registry_api_url that is a cannot-be-a-base URL or otherwise has no mutable path segments — e.g. a deno config `registry`/scope import map entry or DENO_REGISTRY_URL override pointing at something like `data:...`, `mailto:...`, or a custom scheme URL without a standard `scheme://host/path` form. Also triggered if the URL somehow lost its authority so the path cannot be segmented.
Common situations: A misconfigured publish/registry URL in deno.json (scope `endpoints` or custom registry override), a corrupted environment variable used as the registry API URL, copying a non-HTTP URL into the registry config, or a test/mock injecting a placeholder URL like `data:test` instead of a real `https://` base.
Related errors
- Can't convert url ("{}") to filename.
- Can't convert url ("{}") to filename.
- ERR_INVALID_URL
- ERR_INVALID_URL_SCHEME
- Unsupported registry endpoint scheme "{scheme}". Expected "h
AI-assisted analysis of denoland/deno@f7822238ca (2026-08-29).
Data as JSON: /api/errors/0e04a0aed2671d51.
Report an issue: GitHub.