nautechsystems/nautilus_trader · error

Invalid config type for CoinbaseExecutionClientFactory. Expe

Error message

Invalid config type for CoinbaseExecutionClientFactory. Expected CoinbaseExecutionClientConfig, was {config:?}

What it means

CoinbaseExecutionClientFactory::create downcasts the generic ClientConfig to CoinbaseExecutionClientConfig; on failure it raises this error. It guards that execution clients are only built from the execution-specific config type.

Source

Thrown at crates/adapters/coinbase/src/factories.rs:151

    #[must_use]
    pub const fn new() -> Self {
        Self
    }
}

impl ExecutionClientFactory for CoinbaseExecutionClientFactory {
    fn create(
        &self,
        trader_id: TraderId,
        name: &str,
        config: &dyn ClientConfig,
        cache: CacheView,
    ) -> anyhow::Result<Box<dyn ExecutionClient>> {
        let coinbase_config = config
            .as_any()
            .downcast_ref::<CoinbaseExecutionClientConfig>()
            .ok_or_else(|| {
                anyhow::anyhow!(
                    "Invalid config type for CoinbaseExecutionClientFactory. Expected CoinbaseExecutionClientConfig, was {config:?}",
                )
            })?
            .clone();

        let account_type = coinbase_config.account_type;
        if !matches!(account_type, AccountType::Cash | AccountType::Margin) {
            anyhow::bail!(
                "Unsupported account_type {account_type:?} for Coinbase; expected Cash (spot) or Margin (CFM derivatives)"
            );
        }

        let core = ExecutionClientCore::new(
            trader_id,
            ClientId::from(name),
            *COINBASE_VENUE,
            OmsType::Netting,
            coinbase_config.account_id,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Supply CoinbaseExecutionClientConfig to the execution factory's create().
  2. Confirm your node config's execution-client block parses into CoinbaseExecutionClientConfig.
  3. Check that the factory you registered matches the config type you pass (data vs execution).
  4. Update custom config structs to embed/derive from CoinbaseExecutionClientConfig.

Example fix

// before
exec_factory.create(name, &data_config, ...)?;
// after
let exec_config = CoinbaseExecutionClientConfig { account_type: CoinbaseAccountType::Cash, .. };
exec_factory.create(name, &exec_config, ...)?;
Defensive patterns

Strategy: type-guard

Validate before calling

let is_exec_cfg = config.as_any().downcast_ref::<CoinbaseExecutionClientConfig>().is_some();
if !is_exec_cfg { /* fix config wiring before calling the execution factory */ }

Type guard

fn is_coinbase_exec_config(config: &dyn ClientConfig) -> bool {
    config.as_any().downcast_ref::<CoinbaseExecutionClientConfig>().is_some()
}

Prevention

When it happens

Trigger: Calling the execution factory's create() with a CoinbaseDataClientConfig or any non-matching config type, or tests passing a wrong/unsupported config deliberately.

Common situations: Config file sections swapped between data and execution clients, a custom config struct used instead of CoinbaseExecutionClientConfig, or adapter version drift after refactors.

Related errors


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