nautechsystems/nautilus_trader · error
Lighter nonce refresh is pending for connection epoch {conne
Error message
Lighter nonce refresh is pending for connection epoch {connection_epoch} What it means
build_tx_context refuses to prepare a transaction because the nonce-manager has not (re)initialized for the current WebSocket connection epoch. After a Lighter WS reconnect, nonces must be re-synced before any signed tx is built, so all tx preparation is gated on that readiness. This is a deliberate ordering guard, not corruption.
Source
Thrown at crates/adapters/lighter/src/execution.rs:1463
} else {
log::debug!("Lighter auth-token refresh task cancelled");
break;
}
}
})?;
Ok(())
}
// Per-order `params["market_order_slippage_bps"]` overrides the config default.
fn resolve_slippage_bps(&self, params: Option<&Params>) -> u32 {
params
.and_then(|p| p.get_u64("market_order_slippage_bps"))
.map_or(self.config.market_order_slippage_bps, |v| v as u32)
}
fn build_tx_context(&self, credential: &Credential) -> anyhow::Result<ReservedTxContext> {
let connection_epoch = self.ws_client.connection_epoch();
anyhow::ensure!(
self.nonce_ready_connection_epoch.load(Ordering::Acquire) == connection_epoch,
"Lighter nonce refresh is pending for connection epoch {connection_epoch}",
);
let nonce_guard = Arc::clone(&self.nonce_submission_gate)
.try_read_owned()
.context("Lighter nonce refresh is in progress")?;
anyhow::ensure!(
self.ws_client.connection_epoch() == connection_epoch
&& self.nonce_ready_connection_epoch.load(Ordering::Acquire) == connection_epoch,
"Lighter connection or nonce state changed during transaction preparation",
);
let nonce = match self
.dispatch
.nonce_manager
.next_nonce(credential.account_index(), credential.api_key_index())
{
Ok(nonce) => nonce,
Err(e @ NonceError::SkipWindowExhausted { .. }) => {View on GitHub (pinned to 18893faf8b)
Solutions
- Wait for nonce readiness before issuing signed commands: retry after a short delay or await the adapter's ready signal.
- Retry the operation; the nonce refresh completes automatically shortly after connect.
- Check WS connectivity/logs if the condition persists — the refresh may be failing repeatedly.
- Serialize submit logic so commands are not queued before the connection is fully initialized.
Example fix
// before
execution.update_leverage(instrument_id, leverage)?;
// after
if !execution.is_nonce_ready() {
tokio::time::sleep(Duration::from_millis(250)).await; // or await ready signal
}
execution.update_leverage(instrument_id, leverage)?; Defensive patterns
Strategy: retry
Validate before calling
// Rust
if adapter.nonce_ready_epoch() != adapter.connection_epoch() {
return Err("nonce refresh pending; retry after connect settles");
} Try / catch
match adapter.update_leverage(id, lev) {
Err(e) if e.to_string().contains("nonce refresh is pending") => {
tokio::time::sleep(Duration::from_millis(200)).await;
// retry once or twice, then surface
}
other => other,
} Prevention
- Gate all signed commands on the adapter's connection/nonce-ready signal
- Add reconnect-aware dispatch that queues commands until readiness
- Monitor WS reconnect frequency in production
When it happens
Trigger: Any call path that reaches build_tx_context — update_leverage, prepare_signed_modify_order, prepare_integrator_auto_approval — while nonce_ready_connection_epoch still holds an older epoch than ws_client.connection_epoch(), i.e. right after (re)connect before the nonce refresh task completes.
Common situations: Submitting modify-order or leverage updates immediately after a WS disconnect/reconnect or adapter startup; flaky network causing rapid reconnects; calling account-management endpoints before the gateway signals readiness.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Lighter connection or nonce state changed during transaction
- Canonical head changed during signer-nonce replacement scan
- rate limiter decision lock poisoned
- Invalid `ConnectionMode` value: {value}
- Betfair data shutdown failed: {}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/ba6a04a060e5edc6.
Report an issue: GitHub.