jdx/mise · error

setup repository URL must be nonempty and must not start wit

Error message

setup repository URL must be nonempty and must not start with '-'

What it means

`validate_url` in src/system/history/sync/network.rs guards every git network operation (fetch, push, ls-remote, symbolic-head) for the setup repository. A URL that is empty/whitespace, or that starts with `-` after leading whitespace, is rejected before it is ever passed to a git subprocess. This prevents an attacker-controlled or misconfigured value from being interpreted by git as a command-line option (e.g. `--upload-pack=...`) rather than a URL.

Source

Thrown at src/system/history/sync/network.rs:23

use eyre::{Result, bail};

use crate::system::history::shadow::HistoryRepo;

/// The fetched setup branch head.
pub(crate) const UPSTREAM_REF: &str = "refs/remotes/origin/setup";

/// A Git transport failed, as distinct from an invalid local configuration,
/// encryption policy, or reconciliation plan.
#[derive(Debug, thiserror::Error)]
#[error("{0}")]
pub(crate) struct NetworkError(pub String);

/// Authentication belongs in a credential helper or SSH agent, never in
/// persisted connection URLs or the errors recorded in history health.
pub(crate) fn validate_url(value: &str) -> Result<()> {
    if value.trim().is_empty() || value.trim_start().starts_with('-') {
        bail!("setup repository URL must be nonempty and must not start with '-'");
    }
    let http_like = value
        .trim_start()
        .get(..5)
        .is_some_and(|prefix| prefix.eq_ignore_ascii_case("http:"))
        || value
            .trim_start()
            .get(..6)
            .is_some_and(|prefix| prefix.eq_ignore_ascii_case("https:"));
    if http_like && url::Url::parse(value).is_err() {
        bail!("invalid HTTP setup repository URL; use a Git credential helper for authentication");
    }
    if let Ok(url) = url::Url::parse(value) {
        let http = matches!(url.scheme(), "http" | "https");
        if url.password().is_some()
            || (http
                && (!url.username().is_empty()
                    || url.query().is_some()

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Set a real, nonempty setup repository URL (e.g. `git@github.com:user/dotfiles.git`, `https://github.com/user/dotfiles.git`, or a local path) in your settings/config.
  2. Ensure the URL does not begin with `-`; if a leading `-` is genuine, it is not a valid git remote value here — fix or escape the source of the value.
  3. Check for unfilled placeholders or template variables in your config that resolve to empty strings.

Example fix

// before (config)
history.remote = "--upload-pack=evil"

// after
history.remote = "git@github.com:user/dotfiles.git"
Defensive patterns

Strategy: validation

Validate before calling

fn is_safe_remote_url(v: &str) -> bool {
    !v.trim().is_empty() && !v.trim_start().starts_with('-')
}

Try / catch

// Rust
match validate_url(url) {
    Ok(()) => remote.fetch("main")?,
    Err(e) => eprintln!("fix the history.remote setting: {e}"),
}

Prevention

When it happens

Trigger: Calling `Remote::new(repo, value)` followed by `fetch`, `fetch_tip`, `push`, `symbolic_head`, or `ls_remote` where `value` is `""`, whitespace-only, or begins with a `-` (option injection attempt), e.g. a URL of `"--upload-pack=bad"`.

Common situations: An empty `history` remote URL in settings or an environment/config template that left the placeholder unfilled; a malicious or corrupted config value attempting option injection; a script concatenating flags into the URL field; a mis-parsed YAML/TOML value that trimmed the real URL.

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@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/cbf4163796520e08. Report an issue: GitHub.