nautechsystems/nautilus_trader · error
Derive execution startup teardown failed: {teardown_error}
Error message
Derive execution startup teardown failed: {teardown_error} What it means
This error is returned by Derive execution client connect() when subscribing to the private WebSocket channels (orders, balances) fails AND the partial-connect teardown also fails. The original subscription error is preserved as the source, with the teardown error appended, telling the caller the startup failed and cleanup could not complete either — the client may be left in a partially-connected state.
Source
Thrown at crates/adapters/derive/src/execution.rs:647
if let Err(teardown_error) = self.teardown_partial_connect().await {
return Err(e.context(format!(
"Derive execution startup teardown failed: {teardown_error}"
)));
}
return Err(e);
};
let subaccount_id = self.credential.subaccount_id();
let channels = vec![
DeriveWsChannel::orders(subaccount_id),
DeriveWsChannel::private_trades(subaccount_id),
DeriveWsChannel::balances(subaccount_id),
];
if let Err(e) = self.ws_client.subscribe_channels(channels).await {
log::warn!("Derive private WS subscriptions failed: {e}; tearing down");
if let Err(teardown_error) = self.teardown_partial_connect().await {
return Err(anyhow::Error::new(e).context(format!(
"Derive execution startup teardown failed: {teardown_error}"
)));
}
return Err(anyhow::Error::new(e).context("failed Derive private WS subscriptions"));
}
if let Err(e) = self.start_ws_dispatch(rx) {
if let Err(teardown_error) = self.teardown_partial_connect().await {
return Err(e.context(format!(
"Derive execution startup teardown failed: {teardown_error}"
)));
}
return Err(e.context("failed to register Derive execution WebSocket dispatch task"));
}
// Fail-fast if the initial account snapshot cannot load: without it,
// `await_account_registered` would block the full timeout window and
// surface a misleading registration timeout. Tear down the WS weView on GitHub (pinned to 18893faf8b)
Solutions
- Check the chained source error for the original subscription failure cause (auth, network)
- Force-disconnect or recreate the ws_client since teardown failed and state may be inconsistent
- Verify Derive API credentials and subaccount_id are valid before connecting
- Retry connect() with a freshly constructed execution client
- Check Derive service status / network reachability if subscriptions time out
Defensive patterns
Strategy: try-catch
Validate before calling
// Validate credentials and connectivity before subscribing
if !derive_credentials_valid(config) {
return Err(anyhow!("invalid Derive credentials; refusing connect"));
} Type guard
fn is_teardown_failure(err: &anyhow::Error) -> bool {
err.to_string().contains("startup teardown failed")
} Try / catch
match exec_client.connect().await {
Err(e) if is_teardown_failure(&e) => {
// subscribe AND teardown failed: client state unknown, recreate it
let fresh = DeriveExecutionClient::new(config)?;
fresh.connect().await
}
other => other,
} Prevention
- Verify Derive API credentials and subaccount_id before connect
- Recreate the client when teardown fails — state may be inconsistent
- Monitor Derive service status for outages
- Keep connect/teardown logic symmetrical and tested
When it happens
Trigger: ws_client.subscribe_channels(channels) for the Derive private channels returns Err, then teardown_partial_connect().await also returns Err.
Common situations: Derive API auth failure (bad API credentials) causing subscription rejection, followed by a teardown that itself errors (broken WS state); network drop during startup; ws_client in an inconsistent state after the failed subscribe.
Related errors
- failed Derive private WS subscriptions
- invalid Derive subscription channel `{channel}`
- WS user data subscription timed out
- Failed to start Spot public JSON WS bytes task: {e}
- Failed to start Spot public JSON WS handler task: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/65d4a6d5897b3e55.
Report an issue: GitHub.