nautechsystems/nautilus_trader · error · anyhow::Error

Invalid config type for BitmexExecutionClientFactory. Expect

Error message

Invalid config type for BitmexExecutionClientFactory. Expected BitmexExecutionClientConfig, was {config:?}

What it means

BitmexExecutionClientFactory::create only accepts a config that downcasts to BitmexExecutionClientConfig. Any other config type produces this error naming the expected type and the actual config value.

Source

Thrown at crates/adapters/bitmex/src/factories.rs:147

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

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

        let account_id = bitmex_config
            .account_id
            .unwrap_or_else(|| AccountId::from("BITMEX-001"));
        bitmex_config.account_id = Some(account_id);

        let core = ExecutionClientCore::new(
            trader_id,
            ClientId::from(name),
            *BITMEX_VENUE,
            OmsType::Netting,
            account_id,
            AccountType::Margin,
            None, // base_currency

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Pass a BitmexExecutionClientConfig instance to BitmexExecutionClientFactory::create.
  2. Verify the config section in your node config is the execution-client section.
  3. Deserialize the raw config into BitmexExecutionClientConfig before handing it to the factory.
  4. Inspect the was {config:?} dump in the message to identify what was actually passed.

Example fix

// before
let config = BitmexDataClientConfig { ... };
let client = BitmexExecutionClientFactory.create(name, config, cache, clock);
// after
let config = BitmexExecutionClientConfig { api_key, api_secret, ... };
let client = BitmexExecutionClientFactory.create(name, config, cache, clock);
Defensive patterns

Strategy: type-guard

Validate before calling

// Rust
fn is_bitmex_exec_config(config: &dyn Any) -> bool {
    config.downcast_ref::<BitmexExecutionClientConfig>().is_some()
}

Type guard

// Rust
fn as_bitmex_exec_config(config: &dyn Any) -> Option<&BitmexExecutionClientConfig> {
    config.downcast_ref::<BitmexExecutionClientConfig>()
}

Try / catch

// Rust
let cfg = config.as_any()
    .downcast_ref::<BitmexExecutionClientConfig>()
    .ok_or_else(|| anyhow::anyhow!("expected BitmexExecutionClientConfig, got {:?}", config))?;

Prevention

When it happens

Trigger: Calling create on BitmexExecutionClientFactory with a config that is not BitmexExecutionClientConfig — e.g. passing BitmexDataClientConfig, another venue's execution config, or a malformed generic config.

Common situations: Wiring the execution factory with the data client's config, swapping config sections in the node config, or config struct renames after an adapter upgrade.

Related errors


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