FuelLabs/sway · error · anyhow::Error

IPFS API request to {url} failed with status {}

Error message

IPFS API request to {url} failed with status {}

What it means

When fetching via a local IPFS node's HTTP API (POST {api}/api/v0/cat?arg=<cid-path>), a non-success HTTP status from the node triggers this bail with the URL and status code. The transport-level request succeeded (connection errors surface earlier with a different message); the node itself refused or errored.

Source

Thrown at forc-pkg/src/source/ipfs.rs:171

    pub(crate) async fn fetch_with_local_node(&self, dst: &Path) -> Result<()> {
        let cid_path = format!("/ipfs/{}", self.0);
        let api_base = local_ipfs_api_base_url();
        // Kubo RPC endpoints require POST. Published forc packages are stored as a single
        // gzip-compressed tar blob; `/cat` returns those bytes (same payload gateways serve).
        let url = format!(
            "{}/api/v0/cat?arg={}",
            api_base.trim_end_matches('/'),
            urlencoding::encode(&cid_path)
        );

        let client = reqwest::Client::new();
        let response = client
            .post(&url)
            .send()
            .await
            .with_context(|| format!("failed to request IPFS content from {url}"))?;
        if !response.status().is_success() {
            anyhow::bail!(
                "IPFS API request to {url} failed with status {}",
                response.status()
            );
        }

        let bytes = response
            .bytes()
            .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.

View on GitHub (pinned to 47e5e902fa)

Solutions

  1. Confirm the daemon serves the content: curl -X POST "http://127.0.0.1:5001/api/v0/cat?arg=<CID>"
  2. Pin the artifact locally (ipfs pin add <CID>) or warm it with ipfs cat <CID> first
  3. Check the ipfs gateway/API settings in Forc.toml or the forc ipfs configuration
  4. Restart the daemon if it returns 5xx errors
Defensive patterns

Strategy: retry

Validate before calling

async fn ipfs_content_available(api_base: &str, cid: &str) -> bool {
    reqwest::Client::new()
        .post(format!("{api_base}/api/v0/cat?arg={cid}"))
        .send()
        .await
        .map(|r| r.status().is_success())
        .unwrap_or(false)
}
// before building: require ipfs_content_available(&api_base, &cid).await

Prevention

When it happens

Trigger: The local IPFS daemon is running but the CID is not pinned/available (404/500), the api base URL is misconfigured to another service, or the node returns 5xx while serving the content.

Common situations: Forgetting to pin the artifact on the local node; ipfs gateway/API configuration pointing at the wrong endpoint; node in a bad state needing restart.

Related errors


AI-assisted analysis of FuelLabs/sway@47e5e902fa (2026-08-16). Data as JSON: /api/errors/958846b3d819d4a7. Report an issue: GitHub.