nautechsystems/nautilus_trader · error

Invalid config type for LighterExecutionClientFactory. Expec

Error message

Invalid config type for LighterExecutionClientFactory. Expected LighterExecutionClientConfig, was {config:?}

What it means

This error is thrown by LighterExecutionClientFactory::create when the config passed to the factory is not a LighterExecutionClientConfig. The factory downcasts the generic config to the concrete config type and fails fast with anyhow if the downcast returns None, embedding the actual config in Debug form. It exists to catch wiring mistakes between data/exec client factories and their configs.

Source

Thrown at crates/adapters/lighter/src/factories.rs:135

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

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

        // Lighter is a perpetual futures DEX with margin accounts and one
        // position per market on the L2.
        let core = ExecutionClientCore::new(
            trader_id,
            ClientId::from(name),
            lighter_config.resolved_venue(),
            OmsType::Netting,
            lighter_config.account_id,
            AccountType::Margin,
            None,
            cache,
        );

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Construct and pass a LighterExecutionClientConfig (with api_key, private key/account details, etc.) to the factory's create()
  2. Check which factory is being invoked and ensure the registered config type matches the adapter (Lighter)
  3. Print the included {config:?} fragment to see the actual concrete config type that was supplied
  4. Verify config deserialization routed the venue-specific fields to the Lighter execution config, not the data config

Example fix

// before
let client = LighterExecutionClientFactory.create(&lighter_data_config, ...)?;
// after
let exec_config = LighterExecutionClientConfig { /* from the 'lighter' execution section */ };
let client = LighterExecutionClientFactory.create(&exec_config, ...)?;
Defensive patterns

Strategy: type-guard

Validate before calling

fn ensure_lighter_exec_config(cfg: &dyn std::any::Any) -> Option<&LighterExecutionClientConfig> {
    cfg.downcast_ref::<LighterExecutionClientConfig>()
}

Type guard

fn is_lighter_exec_config(cfg: &dyn std::any::Any) -> bool {
    cfg.downcast_ref::<LighterExecutionClientConfig>().is_some()
}

Try / catch

match config.as_any().downcast_ref::<LighterExecutionClientConfig>() {
    Some(c) => build_client(c),
    None => return Err(anyhow::anyhow!("expected LighterExecutionClientConfig, got {config:?}")),
}

Prevention

When it happens

Trigger: Calling LighterExecutionClientFactory::create with any config other than LighterExecutionClientConfig — e.g. passing a LighterDataClientConfig, another venue's ExecutionClientConfig, or a default/generic config struct into create().

Common situations: Miswiring in a node/trading config where the execution client config is built from the wrong venue section; copy-pasting factory registration code and pairing a factory with the wrong config type; tests constructing a client with the data config by mistake.

Related errors


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