nautechsystems/nautilus_trader · error
Unknown product type for '{product_id}'
Error message
Unknown product type for '{product_id}' What it means
parse_instrument maps each Coinbase product to a Nautilus instrument based on its CoinbaseProductType (SPOT, FUTURE, PERPETUAL). When a product carries the Unknown product type, the parser cannot determine which instrument constructor to use and fails with this error naming the product_id.
Source
Thrown at crates/adapters/coinbase/src/http/parse.rs:323
.build()
.unwrap();
Ok(InstrumentAny::CryptoFuture(instrument))
}
/// Parses a Coinbase product into the appropriate Nautilus instrument type.
pub fn parse_instrument(product: &Product, ts_init: UnixNanos) -> anyhow::Result<InstrumentAny> {
match product.product_type {
CoinbaseProductType::Spot => parse_spot_instrument(product, ts_init),
CoinbaseProductType::Future => {
if is_perpetual_product(product) {
parse_perpetual_instrument(product, ts_init)
} else {
parse_future_instrument(product, ts_init)
}
}
CoinbaseProductType::Unknown => {
anyhow::bail!("Unknown product type for '{}'", product.product_id)
}
}
}
/// Determines whether a futures product is a perpetual contract.
///
/// Coinbase returns `contract_expiry_type: "EXPIRING"` for both perpetuals
/// and dated futures, so the `CoinbaseContractExpiryType::Perpetual` variant
/// alone is not sufficient. We check three signals in order:
///
/// 1. `contract_expiry_type == Perpetual` (forward compat if Coinbase fixes the API)
/// 2. Non-empty `funding_rate` in `future_product_details` (structural signal:
/// only perpetuals have ongoing funding)
/// 3. `display_name` contains "PERP" or "Perpetual" (heuristic fallback)
pub(crate) fn is_perpetual_product(product: &Product) -> bool {
if let Some(details) = &product.future_product_details {
if details.contract_expiry_type == CoinbaseContractExpiryType::Perpetual {
return true;View on GitHub (pinned to 18893faf8b)
Solutions
- Check the product_id on Coinbase's API and confirm it is a supported SPOT/FUTURE/PERPETUAL product
- Update CoinbaseProductType and parse_instrument to support the new product type if Coinbase introduced one
- Skip/filter Unknown products when bulk-loading instruments
Example fix
// before
let inst = client.request_instrument("BTC-JAM-UNKNOWN").await?;
// after
let products: Vec<_> = all.filter(|p| p.product_type != CoinbaseProductType::Unknown).collect(); Defensive patterns
Strategy: type-guard
Validate before calling
if product.product_type == CoinbaseProductType::Unknown {
log::warn!("skipping unsupported product {}", product.product_id);
return Ok(None);
} Type guard
fn is_supported_product(p: &CoinbaseProduct) -> bool {
!matches!(p.product_type, CoinbaseProductType::Unknown)
} Prevention
- Filter products by supported product_type before parsing
- Keep the adapter's product-type enum updated with Coinbase API changes
- Whitelist product_ids in config rather than loading everything
When it happens
Trigger: Requesting instruments via request_instruments/request_instrument and Coinbase returns a product whose product_type field deserializes to Unknown (new asset classes, unusual product listings, or API schema changes).
Common situations: Coinbase adds a new product category before the adapter enum is updated; calling request_instrument on a product_id for a product type the adapter does not model (e.g. certain derivatives listings).
Understand the failure class
Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.
Related errors
- Coinbase fill has unknown order side
- failed to parse any of {input_len} Lighter instruments: {}
- instrument update lock poisoned
- Invalid scientific notation exponent '{exponent}': must be a
- {FAILED}: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/8fde3286199262be.
Report an issue: GitHub.