gitbutlerapp/gitbutler · error

Invalid GitHub base URL

Error message

Invalid GitHub base URL

What it means

When building the REST labels URL, `url.path_segments_mut()` returns `Err(())` if the parsed URL cannot have path segments (typically a `cannot-be-a-base` URL, e.g. a malformed or non-hierarchical `base_url` like `data:...` or an empty/invalid scheme). The library surfaces this as 'Invalid GitHub base URL'.

Solutions

  1. Check the configured GitHub base URL (config or env, e.g. for GitHub Enterprise) and correct it to a normal `https://host` URL.
  2. Test with `curl <base_url>/api/v3/...` (Enterprise) or `https://api.github.com` (public) to confirm the URL is well-formed.
  3. Remove trailing slashes/paths that may corrupt URL construction and re-test.
  4. If behind a custom proxy, ensure the proxy URL is a hierarchical http(s) URL.

Example fix

// before
let base_url = "api.github.com";           // no scheme
// after
let base_url = "https://api.github.com";   // valid hierarchical base URL
Defensive patterns

Strategy: validation

Validate before calling

fn valid_base_url(base: &str) -> bool {
    reqwest::Url::parse(base).map(|u| u.has_host() && u.can_be_a_base()).unwrap_or(false)
}
assert!(valid_base_url(base_url), "GitHub base URL must be a hierarchical http(s) URL");

Try / catch

match client.set_label(owner, repo, pr, label).await {
    Err(e) if e.to_string().contains("Invalid GitHub base URL") => {
        eprintln!("Fix the configured GitHub base URL (expected https://host)");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling a labels-related client method with a configured GitHub base URL that parses but cannot hold path segments — e.g. a base URL missing a host, having an unsupported scheme, or being a non-hierarchical URL.

Common situations: Misconfigured GitHub Enterprise base URL (typo, missing `https://`, trailing garbage); pointing `base_url` at a proxy URL that is not a normal http(s) URL; env/config value set to an empty or placeholder string.

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 gitbutlerapp/gitbutler@58e5313667 (2026-09-18). Data as JSON: /api/errors/321cdcc7f513b141. Report an issue: GitHub.

Appendix: source

Thrown at crates/but-github/src/client.rs:2285

/// percent-encoded. `PathSegmentsMut::push` silently *drops* `.` and `..`
/// segments, which would degrade this into GitHub's remove-ALL-labels
/// endpoint — refuse those names instead of encoding them.
fn label_removal_url(
    base_url: &str,
    owner: &str,
    repo: &str,
    pr_number: i64,
    label: &str,
) -> Result<reqwest::Url> {
    if matches!(label, "" | "." | "..") {
        bail!("Refusing to remove label with degenerate name {label:?}");
    }

    let mut url = reqwest::Url::parse(&format!(
        "{base_url}/repos/{owner}/{repo}/issues/{pr_number}/labels"
    ))?;
    url.path_segments_mut()
        .map_err(|()| anyhow::anyhow!("Invalid GitHub base URL"))?
        .push(label);
    Ok(url)
}

/// A submitted review on a pull request, with the reactions left on it.
#[derive(Debug, Serialize)]
pub struct PullRequestReview {
    pub id: i64,
    pub author: Option<GitHubUser>,
    /// GitHub state string: `APPROVED`, `CHANGES_REQUESTED`, `COMMENTED`,
    /// `DISMISSED`, or `PENDING` (the caller's own unsubmitted draft).
    pub state: String,
    pub body: Option<String>,
    pub submitted_at: Option<String>,
    pub html_url: String,
    pub reactions: Vec<Reaction>,
}

View on GitHub (pinned to 58e5313667)