nautechsystems/nautilus_trader · error · anyhow::Error

Invalid config type for BinanceExecutionClientFactory. Expec

Error message

Invalid config type for BinanceExecutionClientFactory. Expected BinanceExecutionClientConfig, was {config:?}

What it means

The Binance execution client factory received a runtime config object whose concrete type is not BinanceExecutionClientConfig. It downcasts the generic config to the expected type via downcast_ref and fails with this message when the downcast returns None, so a Binance execution client can never be constructed from a mismatched config.

Source

Thrown at crates/adapters/binance/src/factories.rs:155

impl Default for BinanceExecutionClientFactory {
    fn default() -> Self {
        Self::new()
    }
}

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

        let product_type = binance_config.product_type;

        binance_config.validate()?;

        match product_type {
            BinanceProductType::Spot => {
                // Spot uses cash account type and hedging OMS
                let account_type = AccountType::Cash;
                let oms_type = OmsType::Hedging;

                let core = ExecutionClientCore::new(
                    trader_id,
                    ClientId::from(name),

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Pass a BinanceExecutionClientConfig instance for the execution client factory registration
  2. Check that the venue/config key you registered maps to the exec factory, not the data factory
  3. Re-serialize/deserialize configs with the correct concrete type and keep adapter versions in sync
  4. Log {config:?} in the message output to identify which type was actually supplied

Example fix

// before
config: BinanceDataClientConfig { .. } // registered for exec factory
// after
let exec_config = BinanceExecutionClientConfig {
    api_key,
    api_secret,
    product_type: BinanceProductType::UsdTFuture,
    ..Default::default()
};
factory.create(exec_config, cache).await
Defensive patterns

Strategy: type-guard

Validate before calling

fn is_binance_exec_config(cfg: &dyn ClientConfig) -> bool {
    cfg.as_any().downcast_ref::<BinanceExecutionClientConfig>().is_some()
}

Type guard

fn as_binance_exec_config(cfg: &dyn ClientConfig) -> Option<&BinanceExecutionClientConfig> {
    cfg.as_any().downcast_ref::<BinanceExecutionClientConfig>()
}

Try / catch

match factory.create(config.clone(), cache).await {
    Ok(client) => client,
    Err(e) if e.to_string().contains("Invalid config type") => {
        return Err(anyhow!("wrong config type for exec factory: {}", e));
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling create() on BinanceExecutionClientFactory with a config that is a different client's config struct (e.g. BinanceDataClientConfig, BinanceFuturesExecutionClientConfig-style type, or a generic ClientConfig) passed in the config registry for the BINANCE_EXEC venue.

Common situations: Config typed for the Binance data client but registered for the exec client; mixing adapter versions where the exec config type was renamed; passing a deserialized generic config map instead of the concrete typed struct.

Related errors


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