FuelLabs/sway · error · anyhow::Error
Failed to fetch from {fetch_url:?}
Error message
Failed to fetch from {fetch_url:?} What it means
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.
Source
Thrown at forc-pkg/src/source/ipfs.rs:197
.await
.context("failed to read IPFS API response body")?;
let tar = GzDecoder::new(bytes.as_ref());
self.extract_archive(tar, dst)?;
Ok(())
}
/// Using the provided gateway url, fetches the content described by this cid.
pub(crate) async fn fetch_with_gateway_url(&self, gateway_url: &str, dst: &Path) -> Result<()> {
let client = reqwest::Client::new();
// We request the content to be served to us in tar format by the public gateway.
let fetch_url = format!(
"{}/ipfs/{}?download=true&filename={}.tar.gz",
gateway_url, self.0, self.0
);
let req = client.get(&fetch_url);
let res = req.send().await?;
if !res.status().is_success() {
anyhow::bail!("Failed to fetch from {fetch_url:?}");
}
let bytes: Vec<_> = res.bytes().await?.into_iter().collect();
let tar = GzDecoder::new(bytes.as_slice());
// After collecting and decoding bytes of the archive, we unpack it to the dst.
self.extract_archive(tar, dst)?;
Ok(())
}
}
/// Returns the local IPFS HTTP API base URL, matching `IpfsClient::default()` behavior.
fn local_ipfs_api_base_url() -> String {
read_ipfs_api_base_url_from_config().unwrap_or_else(|| DEFAULT_LOCAL_IPFS_API.to_string())
}
fn read_ipfs_api_base_url_from_config() -> Option<String> {
let home = std::env::var_os("HOME").or_else(|| std::env::var_os("USERPROFILE"))?;
let api_path = Path::new(&home).join(".ipfs").join("api");
let contents = std::fs::read_to_string(api_path).ok()?;View on GitHub (pinned to 47e5e902fa)
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
Example fix
# before: single-shot build in CI that fails on transient gateway errors forc build # after: retry with backoff for i in 1 2 3; do forc build && break || sleep $((i*10)); done
Defensive patterns
Strategy: fallback
Validate before calling
async fn gateway_serves(gateway: &str, cid: &str) -> bool {
let url = format!("{gateway}/ipfs/{cid}?download=true");
reqwest::Client::new()
.get(&url)
.send()
.await
.map(|r| r.status().is_success())
.unwrap_or(false)
}
// before building: try gateways in order and configure the first healthy one Prevention
- 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
When it happens
Trigger: 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.
Common situations: CI builds hammering public gateways; corporate networks blocking IPFS gateways; typos in cids; gateway outages.
Related errors
- offline fetching for IPFS sources is not supported
- IPFS API request to {url} failed with status {}
- Unable to fetch pkg {:?} from {:?} in offline mode
- failed to find package `{}` in {}
AI-assisted analysis of FuelLabs/sway@47e5e902fa (2026-08-16).
Data as JSON: /api/errors/6493bfe11498f00b.
Report an issue: GitHub.