nautechsystems/nautilus_trader · error
Invalid config type for AxExecutionClientFactory. Expected A
Error message
Invalid config type for AxExecutionClientFactory. Expected AxExecutionClientConfig, was {config:?} What it means
AxExecutionClientFactory::create downcasts the generic config to `AxExecutionClientConfig`; any other config type causes this error, echoing the received config's debug output. Like its data-client sibling, it is a factory type guard.
Source
Thrown at crates/adapters/architect_ax/src/factories.rs:204
impl Default for AxExecutionClientFactory {
fn default() -> Self {
Self::new()
}
}
impl ExecutionClientFactory for AxExecutionClientFactory {
fn create(
&self,
trader_id: TraderId,
name: &str,
config: &dyn ClientConfig,
cache: CacheView,
) -> anyhow::Result<Box<dyn ExecutionClient>> {
let ax_config = config
.as_any()
.downcast_ref::<AxExecutionClientConfig>()
.ok_or_else(|| {
anyhow::anyhow!(
"Invalid config type for AxExecutionClientFactory. Expected AxExecutionClientConfig, was {config:?}",
)
})?
.clone();
// AX uses netting for perpetual futures
let oms_type = OmsType::Netting;
let account_type = AccountType::Margin;
let core = ExecutionClientCore::new(
trader_id,
ClientId::from(name),
*AX_VENUE,
oms_type,
ax_config.account_id,
account_type,
None, // base_currency
cache,View on GitHub (pinned to 18893faf8b)
Solutions
- Pass an `AxExecutionClientConfig` to the execution factory.
- Check the `{config:?}` text in the message to identify the wrongly passed type.
- Ensure each venue config block is routed to its matching factory (data config -> data factory, execution config -> execution factory).
- If using a builder/generic loader, add explicit per-factory config construction instead of reusing one struct.
Example fix
// before
let exec_config = AxDataClientConfig { ... };
factory.create(name, exec_config, ...)?; // wrong type
// after
let exec_config = AxExecutionClientConfig {
api_key: Some(api_key),
api_secret: Some(api_secret),
..Default::default()
};
factory.create(name, exec_config, ...)?; Defensive patterns
Strategy: type-guard
Validate before calling
// before calling the execution factory
let Some(_) = config.as_any().downcast_ref::<AxExecutionClientConfig>() else {
panic!("config passed to AxExecutionClientFactory must be AxExecutionClientConfig");
}; Type guard
fn as_ax_exec_config(config: &dyn Any) -> Option<&AxExecutionClientConfig> {
config.downcast_ref::<AxExecutionClientConfig>()
} Try / catch
match factory.create(name, config, cache, ...) {
Err(e) if e.to_string().contains("Invalid config type for AxExecutionClientFactory") => {
return Err(anyhow::anyhow!("pass AxExecutionClientConfig to the execution factory: {e}"));
}
other => other,
} Prevention
- Keep data and execution config construction in separate, clearly named functions.
- Route configs to factories via explicit type dispatch, not positional wiring.
- Add a bootstrap unit test that builds both AX clients from real config structs.
- Check the echoed `{config:?}` whenever this fires to spot the swapped type quickly.
When it happens
Trigger: Calling `AxExecutionClientFactory.create(name, config, ...)` with a config that is not `AxExecutionClientConfig` — commonly an `AxDataClientConfig` or a generic/other-venue execution config.
Common situations: Swapping data/execution configs in a multi-adapter bootstrap; passing a shared base config struct; registering the AX execution factory under a name whose config block belongs to the data client.
Related errors
- Invalid config type for AxDataClientFactory. Expected AxData
- Invalid config type for DeriveDataClientFactory. Expected De
- Invalid config type for KrakenDataClientFactory. Expected Kr
- Invalid config type for AxExecutionClientFactory. Expected A
- Unsupported blockchain {blockchain} for RPC connection
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/be6cf270158c1a3b.
Report an issue: GitHub.