jdx/mise · error

remote bootstrap requires HTTPS, SSH, or a local path

Error message

remote bootstrap requires HTTPS, SSH, or a local path

What it means

Remote onboarding only supports HTTPS, SSH, or file schemes. validate_origin parses any origin containing `://` and bails if the URL scheme is not one of https, ssh, or file. This keeps bootstrap limited to transports whose authentication mise can delegate to local Git.

Solutions

  1. Switch the origin to an https:// URL.
  2. Use an SSH URL (ssh://user@host/path or scp-style user@host:path) if SSH auth is configured.
  3. For local repositories, use a plain filesystem path (which bypasses the URL check via explicit_local) or a file:// URL.
  4. If you must use git:// or http://, host a mirror over HTTPS.

Example fix

// before
install_at("git://github.com/org/repo.git", rev, ...).await?;
// after
install_at("https://github.com/org/repo.git", rev, ...).await?;
Defensive patterns

Strategy: validation

Validate before calling

function isSupportedScheme(origin: string): boolean {
  try { return ["https", "ssh", "file"].includes(new URL(origin).protocol.replace(":", "")); }
  catch { return !origin.includes("://"); } // local path
}

Type guard

const isHttpsOrSsh = (s: string): boolean => /^https:\/\/|^ssh:\/\//.test(s);

Prevention

When it happens

Trigger: Calling Source::fetch or install_at with an origin whose URL scheme is e.g. `git://`, `http://`, `ftp://`, `rsync://`, or a custom scheme, while the origin is not an explicitly local path.

Common situations: Using an old-style `git://` GitHub URL, an internal `http://` mirror, or a company scheme like `arc://` in the source repository setting.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/416ea8c5f61307a0. Report an issue: GitHub.

Appendix: source

Thrown at src/system/remote_repository.rs:62

pub(crate) fn validate_origin(origin: &str) -> Result<()> {
    if origin.starts_with('-') || origin.chars().any(char::is_control) {
        bail!("invalid repository origin");
    }
    // Explicit local paths may contain colons; otherwise :: selects a Git helper.
    let explicit_local = std::path::Path::new(origin).is_absolute()
        || origin.starts_with("./")
        || origin.starts_with("../");
    if !explicit_local
        && origin.split_once("::").is_some_and(|(prefix, _)| {
            !prefix.is_empty() && !prefix.contains(['/', '\\', '[', ']', '@', ':'])
        })
    {
        bail!("Git remote helpers are not supported for remote onboarding");
    }
    if !explicit_local && origin.contains("://") {
        let url = url::Url::parse(origin).wrap_err("invalid repository URL")?;
        if !matches!(url.scheme(), "https" | "ssh" | "file") {
            bail!("remote bootstrap requires HTTPS, SSH, or a local path");
        }
    }
    if let Ok(url) = url::Url::parse(origin)
        && (url.password().is_some()
            || (url.scheme() != "ssh" && !url.username().is_empty())
            || url.query().is_some()
            || url.fragment().is_some())
    {
        bail!("repository origin must not contain credentials, query parameters, or fragments");
    }
    Ok(())
}

impl Source {
    pub(crate) async fn fetch(origin: String) -> Result<Self> {
        validate_origin(&origin)?;
        let directory = tempfile::tempdir()?;
        let repo = directory.path().join("repo");

View on GitHub (pinned to 533346cc37)