{"record":{"id":"6493bfe11498f00b","repo":"FuelLabs/sway","slug":"failed-to-fetch-from-fetch-url","errorCode":null,"errorMessage":"Failed to fetch from {fetch_url:?}","messagePattern":"Failed to fetch from (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"forc-pkg/src/source/ipfs.rs","lineNumber":197,"sourceCode":"            .await\n            .context(\"failed to read IPFS API response body\")?;\n        let tar = GzDecoder::new(bytes.as_ref());\n        self.extract_archive(tar, dst)?;\n        Ok(())\n    }\n\n    /// Using the provided gateway url, fetches the content described by this cid.\n    pub(crate) async fn fetch_with_gateway_url(&self, gateway_url: &str, dst: &Path) -> Result<()> {\n        let client = reqwest::Client::new();\n        // We request the content to be served to us in tar format by the public gateway.\n        let fetch_url = format!(\n            \"{}/ipfs/{}?download=true&filename={}.tar.gz\",\n            gateway_url, self.0, self.0\n        );\n        let req = client.get(&fetch_url);\n        let res = req.send().await?;\n        if !res.status().is_success() {\n            anyhow::bail!(\"Failed to fetch from {fetch_url:?}\");\n        }\n        let bytes: Vec<_> = res.bytes().await?.into_iter().collect();\n        let tar = GzDecoder::new(bytes.as_slice());\n        // After collecting and decoding bytes of the archive, we unpack it to the dst.\n        self.extract_archive(tar, dst)?;\n        Ok(())\n    }\n}\n\n/// Returns the local IPFS HTTP API base URL, matching `IpfsClient::default()` behavior.\nfn local_ipfs_api_base_url() -> String {\n    read_ipfs_api_base_url_from_config().unwrap_or_else(|| DEFAULT_LOCAL_IPFS_API.to_string())\n}\n\nfn read_ipfs_api_base_url_from_config() -> Option<String> {\n    let home = std::env::var_os(\"HOME\").or_else(|| std::env::var_os(\"USERPROFILE\"))?;\n    let api_path = Path::new(&home).join(\".ipfs\").join(\"api\");\n    let contents = std::fs::read_to_string(api_path).ok()?;","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/FuelLabs/sway/blob/47e5e902faa42baf652dd6a0c88cd23390c1a614/forc-pkg/src/source/ipfs.rs#L179-L215","documentation":"Fallback fetch path used when the local API is not available: forc GETs {gateway}/ipfs/<cid>?download=true&filename=<cid>.tar.gz from a public (or configured) gateway and bails on any non-success status, printing the full URL.","triggerScenarios":"The public IPFS gateway rate-limits or returns 429/5xx, the gateway is temporarily down, or the CID is invalid/unknown so the gateway returns an error status.","commonSituations":"CI builds hammering public gateways; corporate networks blocking IPFS gateways; typos in cids; gateway outages.","solutions":["Retry after a short wait - public gateway failures are frequently transient","Configure a different/custom gateway for the ipfs node setting in Forc.toml, or run a local node (which switches to the local API path)","Verify the cid resolves by opening {gateway}/ipfs/<cid> in a browser","Self-host a gateway or pin the content on a local node for reliability"],"exampleFix":"# before: single-shot build in CI that fails on transient gateway errors\nforc build\n\n# after: retry with backoff\nfor i in 1 2 3; do forc build && break || sleep $((i*10)); done","handlingStrategy":"fallback","validationCode":"async fn gateway_serves(gateway: &str, cid: &str) -> bool {\n    let url = format!(\"{gateway}/ipfs/{cid}?download=true\");\n    reqwest::Client::new()\n        .get(&url)\n        .send()\n        .await\n        .map(|r| r.status().is_success())\n        .unwrap_or(false)\n}\n// before building: try gateways in order and configure the first healthy one","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pin ipfs dependencies on a local node instead of relying on public gateways","Configure a stable/custom gateway in Forc.toml for CI","Wrap CI builds in retry with backoff for transient 429/5xx gateway responses"],"tags":["ipfs","network","gateway","retry"],"backgroundTag":null,"analyzedSha":"47e5e902faa42baf652dd6a0c88cd23390c1a614","analyzedAt":"2026-08-16T07:57:45.555Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}