{"record":{"id":"d3ba43521b8d1b6f","repo":"zed-industries/zed","slug":"failed-to-get-host-from-forgejo-base-url","errorCode":null,"errorMessage":"failed to get host from forgejo base url","messagePattern":"failed to get host from forgejo base url","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/git_hosting_providers/src/providers/forgejo.rs","lineNumber":116,"sourceCode":"        if !host.contains(\"forgejo\") {\n            bail!(\"not a Forgejo URL\");\n        }\n\n        Ok(Self::new(\n            \"Forgejo Self-Hosted\",\n            Url::parse(&format!(\"https://{}\", host))?,\n        ))\n    }\n\n    async fn fetch_forgejo_commit_author(\n        &self,\n        repo_owner: &str,\n        repo: &str,\n        commit: &str,\n        client: &Arc<dyn HttpClient>,\n    ) -> Result<Option<User>> {\n        let Some(host) = self.base_url.host_str() else {\n            bail!(\"failed to get host from forgejo base url\");\n        };\n        let url = format!(\n            \"https://{host}/api/v1/repos/{repo_owner}/{repo}/git/commits/{commit}?stat=false&verification=false&files=false\"\n        );\n\n        let mut request = Request::get(&url)\n            .header(\"Content-Type\", \"application/json\")\n            .follow_redirects(http_client::RedirectPolicy::FollowAll);\n\n        // TODO: not renamed yet for compatibility reasons, may require a refactor later\n        // see https://github.com/zed-industries/zed/issues/11043#issuecomment-3480446231\n        if host == \"codeberg.org\"\n            && let Ok(codeberg_token) = std::env::var(\"CODEBERG_TOKEN\")\n        {\n            request = request.header(\"Authorization\", format!(\"Bearer {}\", codeberg_token));\n        }\n\n        let mut response = client","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/git_hosting_providers/src/providers/forgejo.rs#L98-L134","documentation":"The Forgejo provider needs the hostname of its stored base_url to build API endpoints of the form https://{host}/api/v1/repos/{owner}/{repo}/git/commits/{sha}. Url::host_str() returns None when the parsed URL carries no host component, so the code bails before it can construct the request URL. This is almost always a misconfigured provider URL rather than a network failure.","triggerScenarios":"Instantiating a Forgejo provider whose base_url parses as a URL but has no authority component (e.g. file:///path, unix:/run/forgejo.sock, data:..., or an empty/relative string that slipped through construction), then invoking any code path that reaches fetch_forgejo_commit_author (commit author enrichment for a permalink).","commonSituations":"Settings where the Forgejo URL was entered without a scheme or host (e.g. a raw 'forgejo.mycompany.com'), test fixtures using placeholder URLs, or refactors that pass an already-stripped URL into the provider.","solutions":["Set the Forgejo base URL to a fully-qualified form such as https://forgejo.example.com","Validate at provider construction: parse the URL and ensure host_str() is Some and non-empty, so the bad value is rejected early with the offending string in the message","Normalize and verify URL inputs in the settings layer before a provider is created"],"exampleFix":"// before\nlet base_url = Url::parse(&raw_url)?; // may lack a host; fails later inside fetch_forgejo_commit_author\n\n// after: fail fast at construction with the offending value\nlet base_url = Url::parse(&raw_url)?;\nanyhow::ensure!(\n    base_url.host_str().is_some_and(|h| !h.is_empty()),\n    \"forgejo base url '{raw_url}' has no host\"\n);","handlingStrategy":"validation","validationCode":"// run before constructing/calling the provider\nlet parsed = Url::parse(&configured_url)?;\nanyhow::ensure!(\n    parsed.host_str().is_some_and(|host| !host.is_empty()),\n    \"forgejo url '{configured_url}' must include scheme and host\"\n);","typeGuard":"fn has_url_host(url: &Url) -> bool {\n    url.host_str().is_some_and(|h| !h.is_empty())\n}","tryCatchPattern":"match fetch_commit_author(owner, repo, sha).await {\n    Ok(author) => { /* ... */ }\n    Err(err) if err.to_string().contains(\"failed to get host\") => {\n        // configuration problem: surface it, do not retry\n    }\n    Err(err) => return Err(err),\n}","preventionTips":["Always configure provider base URLs with scheme and host (https://host)","Add a settings-level validator that parses the URL and requires a host before any provider is instantiated","Include the offending URL in error context so misconfiguration is immediately visible"],"tags":["forgejo","url-parsing","git-hosting","rust","configuration"],"backgroundTag":"invalid-url-config","analyzedSha":"f4178619acd0d47ea1f76a2025c42962c6d6638c","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}