nautechsystems/nautilus_trader · error · anyhow::Error

Invalid config type for DydxExecutionClientFactory. Expected

Error message

Invalid config type for DydxExecutionClientFactory. Expected DydxExecutionClientConfig, was {config:?}

What it means

DydxExecutionClientFactory::create downcasts the incoming config to DydxExecutionClientConfig. If the config is any other type (e.g. DydxDataClientConfig or another adapter's config), the downcast returns None and this error is raised instead of constructing the execution client.

Source

Thrown at crates/adapters/dydx/src/factories.rs:195

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

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

        // dYdX uses netting for perpetual futures
        let oms_type = OmsType::Netting;

        // dYdX is always margin (perpetual futures)
        let account_type = AccountType::Margin;

        let core = ExecutionClientCore::new(
            trader_id,
            ClientId::from(name),
            *DYDX_VENUE,
            oms_type,
            dydx_config.account_id,
            account_type,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Pass a DydxExecutionClientConfig (with wallet key, network, etc.) to DydxExecutionClientFactory.create.
  2. Ensure the node configuration maps the execution-client section to DydxExecutionClientConfig and the data-client section to DydxDataClientConfig.
  3. Construct the config from the dydx adapter's exported config class rather than a generic dict/other adapter class.
  4. Log config.type before calling create to confirm the exact concrete type at runtime.

Example fix

# before
# exec_config = DydxDataClientConfig(...)  # wrong type
# factory.create(name, exec_config, cache, ...)
# after
exec_config = DydxExecutionClientConfig(dextra_env=..., api_key=..., ...)
client = DydxExecutionClientFactory().create(name, exec_config, cache, ...)
Defensive patterns

Strategy: type-guard

Validate before calling

assert isinstance(config, DydxExecutionClientConfig), f"expected DydxExecutionClientConfig, got {type(config)}"

Type guard

fn as_dydx_exec_config(config: &dyn ExecutionClientConfig) -> Option<&DydxExecutionClientConfig> {
    config.as_any().downcast_ref::<DydxExecutionClientConfig>()
}

Try / catch

match DydxExecutionClientFactory().create(name, config, cache) {
    Ok(c) => c,
    Err(e) if e.to_string().contains("Invalid config type") => {
        // log config.type and correct the wiring
        panic!("wrong config for execution factory: {e}")
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling DydxExecutionClientFactory.create(name, config, cache, ...) with a config object that is not DydxExecutionClientConfig — typically the data client config or a config from a different venue adapter.

Common situations: Mixing up config blocks in the trading node YAML/JSON so the execution factory receives the data config; copy-pasting factory wiring code between data and execution client setup; tests asserting the factory rejects wrong configs.

Related errors


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