nautechsystems/nautilus_trader · error
Client already registered with ID {client_id}
Error message
Client already registered with ID {client_id} What it means
ExecutionEngine.register_client refuses to register a second ExecutionClient whose ClientId already exists in self.clients. Client IDs must be unique within the engine; the duplicate is rejected before any routing map is touched.
Source
Thrown at crates/execution/src/engine/mod.rs:360
}
#[must_use]
/// Returns any external order claim for the given instrument ID.
pub fn get_external_order_claim(&self, instrument_id: &InstrumentId) -> Option<StrategyId> {
self.cache.borrow().external_order_claim(instrument_id)
}
/// Registers a new execution client.
///
/// # Errors
///
/// Returns an error if a client with the same ID is already registered.
pub fn register_client(&mut self, client: Box<dyn ExecutionClient>) -> anyhow::Result<()> {
let client_id = client.client_id();
let venue = client.venue();
if self.clients.contains_key(&client_id) {
anyhow::bail!("Client already registered with ID {client_id}");
}
let adapter = ExecutionClientAdapter::new(client);
if let Some(existing_client_id) = self.routing_map.get(&venue) {
anyhow::bail!(
"Venue {venue} already routed to {existing_client_id}, \
cannot register {client_id} for the same venue"
);
}
self.routing_map.insert(venue, client_id);
log::debug!("Registered client {client_id}");
self.clients.insert(client_id, adapter);
Ok(())
}
/// Registers a default execution client for fallback routing.View on GitHub (pinned to 18893faf8b)
Solutions
- Ensure each client has a unique ClientId before registration
- Check contains/lookup before registering, or reuse the existing registered client
- Fix the config so the same adapter is not instantiated twice
Example fix
// before
engine.register_client(client_a.clone())?;
engine.register_client(client_a)?; // duplicate ClientId
// after
if !engine.clients_registered().contains(&client_a.client_id()) {
engine.register_client(client_a)?;
} Defensive patterns
Strategy: validation
Validate before calling
if engine.registered_client_ids().contains(&client.client_id()) {
return Err(anyhow!("duplicate client {}", client.client_id()));
} Try / catch
match engine.register_client(client) {
Err(e) if e.to_string().contains("already registered") => {/* reuse existing client */},
other => other?,
} Prevention
- Generate unique ClientIds per adapter instance in config
- Guard startup code against double-registration on retry
- Assert uniqueness of client IDs in test fixtures
When it happens
Trigger: Calling register_client twice with clients reporting the same client_id() — e.g. constructing two adapters for the same venue/client and registering both at startup.
Common situations: Duplicate adapter instantiation in a live-trading config (same client id configured twice); test setups re-registering a fixture client; a retry path that re-registers instead of reusing the existing client.
Related errors
- Venue {venue} already routed to {existing_client_id}, cannot
- Order for {} not found to determine position ID
- default client already registered
- No client registered with ID {client_id}
- Client {client_id} not found
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/7750f8f373756d46.
Report an issue: GitHub.