nautechsystems/nautilus_trader · error

Failed to fetch products: {e}

Error message

Failed to fetch products: {e}

What it means

Raised by CoinbaseHttpClient::request_instruments when the underlying get_products() HTTP call to Coinbase's /products endpoint fails. The REST error is wrapped with context; parsing failures of the returned JSON raise separate errors afterward.

Source

Thrown at crates/adapters/coinbase/src/http/client.rs:1029

    /// Requests all instruments from Coinbase, optionally filtered by product type.
    ///
    /// Parses each supported product into a Nautilus [`InstrumentAny`] and caches
    /// the results in the shared instrument map. Unsupported products (non-crypto
    /// futures, `UNKNOWN` product types) are skipped with a debug log.
    ///
    /// # Errors
    ///
    /// Returns an error when the HTTP request fails or the response cannot be
    /// deserialized.
    pub async fn request_instruments(
        &self,
        product_type: Option<CoinbaseProductType>,
    ) -> anyhow::Result<Vec<InstrumentAny>> {
        let json = self
            .inner
            .get_products()
            .await
            .map_err(|e| anyhow::anyhow!("Failed to fetch products: {e}"))?;
        let response: ProductsResponse =
            serde_json::from_value(json).map_err(|e| anyhow::anyhow!(e))?;

        let ts_init = self.ts_now();
        let mut instruments = Vec::with_capacity(response.products.len());

        for product in &response.products {
            if let Some(filter) = product_type
                && product.product_type != filter
            {
                continue;
            }

            match parse_instrument(product, ts_init) {
                Ok(instrument) => instruments.push(instrument),
                Err(e) => {
                    log::debug!(
                        "Skipping product '{}' during parse: {e}",

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check network connectivity and that api.coinbase.com is reachable from the host.
  2. Inspect the wrapped {e} for HTTP status; handle 429 with backoff and retry.
  3. Verify proxy_url in config is correct if behind a proxy.
  4. Retry request_instruments after checking Coinbase status for outages.

Example fix

// before
let instruments = client.request_instruments(None).await?;
// after (retry with backoff)
match client.request_instruments(None).await {
    Ok(i) => i,
    Err(e) => { tracing::warn!("products fetch failed: {e}"); tokio::time::sleep(Duration::from_secs(5)).await; client.request_instruments(None).await?; }
};
Defensive patterns

Strategy: retry

Validate before calling

fn endpoint_reachable(url: &str) -> bool {
    std::net::TcpStream::connect((url_host(url), 443)).is_ok()
}

Try / catch

match client.request_instruments(None).await {
    Ok(i) => i,
    Err(e) => { warn!("products fetch failed: {e}; retrying"); backoff_retry(|| client.request_instruments(None)).await? }
}

Prevention

When it happens

Trigger: Any request_instruments() call where get_products() returns Err: network failure, DNS failure, HTTP 4xx/5xx, timeout, or TLS problems against api.coinbase.com.

Common situations: No internet or corporate proxy blocking the API, Coinbase exchange API outage or rate limiting (429), invalid proxy_url configured, or wrong base/ws URL env.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/4fe4a8f5be23eca5. Report an issue: GitHub.