{"record":{"id":"321cdcc7f513b141","repo":"gitbutlerapp/gitbutler","slug":"invalid-github-base-url","errorCode":null,"errorMessage":"Invalid GitHub base URL","messagePattern":"Invalid GitHub base URL","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-github/src/client.rs","lineNumber":2285,"sourceCode":"/// percent-encoded. `PathSegmentsMut::push` silently *drops* `.` and `..`\n/// segments, which would degrade this into GitHub's remove-ALL-labels\n/// endpoint — refuse those names instead of encoding them.\nfn label_removal_url(\n    base_url: &str,\n    owner: &str,\n    repo: &str,\n    pr_number: i64,\n    label: &str,\n) -> Result<reqwest::Url> {\n    if matches!(label, \"\" | \".\" | \"..\") {\n        bail!(\"Refusing to remove label with degenerate name {label:?}\");\n    }\n\n    let mut url = reqwest::Url::parse(&format!(\n        \"{base_url}/repos/{owner}/{repo}/issues/{pr_number}/labels\"\n    ))?;\n    url.path_segments_mut()\n        .map_err(|()| anyhow::anyhow!(\"Invalid GitHub base URL\"))?\n        .push(label);\n    Ok(url)\n}\n\n/// A submitted review on a pull request, with the reactions left on it.\n#[derive(Debug, Serialize)]\npub struct PullRequestReview {\n    pub id: i64,\n    pub author: Option<GitHubUser>,\n    /// GitHub state string: `APPROVED`, `CHANGES_REQUESTED`, `COMMENTED`,\n    /// `DISMISSED`, or `PENDING` (the caller's own unsubmitted draft).\n    pub state: String,\n    pub body: Option<String>,\n    pub submitted_at: Option<String>,\n    pub html_url: String,\n    pub reactions: Vec<Reaction>,\n}\n","sourceCodeStart":2267,"sourceCodeEnd":2303,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-github/src/client.rs#L2267-L2303","documentation":"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'.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the configured GitHub base URL (config or env, e.g. for GitHub Enterprise) and correct it to a normal `https://host` URL.","Test with `curl <base_url>/api/v3/...` (Enterprise) or `https://api.github.com` (public) to confirm the URL is well-formed.","Remove trailing slashes/paths that may corrupt URL construction and re-test.","If behind a custom proxy, ensure the proxy URL is a hierarchical http(s) URL."],"exampleFix":"// before\nlet base_url = \"api.github.com\";           // no scheme\n// after\nlet base_url = \"https://api.github.com\";   // valid hierarchical base URL","handlingStrategy":"validation","validationCode":"fn valid_base_url(base: &str) -> bool {\n    reqwest::Url::parse(base).map(|u| u.has_host() && u.can_be_a_base()).unwrap_or(false)\n}\nassert!(valid_base_url(base_url), \"GitHub base URL must be a hierarchical http(s) URL\");","typeGuard":null,"tryCatchPattern":"match client.set_label(owner, repo, pr, label).await {\n    Err(e) if e.to_string().contains(\"Invalid GitHub base URL\") => {\n        eprintln!(\"Fix the configured GitHub base URL (expected https://host)\");\n    }\n    other => other?,\n}","preventionTips":["Validate the GitHub base URL at config load time (scheme + host present)","Use https://api.github.com for public GitHub and https://host/api/v3 for Enterprise","Avoid placeholder or empty base URLs in config/env"],"tags":["github","url","configuration","base-url"],"backgroundTag":"invalid-url-format","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}