nautechsystems/nautilus_trader · error

Signer not initialized; connect the client first

Error message

Signer not initialized; connect the client first

What it means

This error is raised in prepare_swap (called from submit_order) when the blockchain execution client has no signer configured. A swap transaction cannot be signed or submitted without a signer (private key/wallet), so the client fails fast before building the swap call. Call client.connect(...) with signer credentials before submitting orders that require swaps.

Solutions

  1. Call client.connect(...) with valid signer credentials before submit_order
  2. Verify the client config includes a private key, keystore, or KMS signer reference
  3. Check that connect() succeeded and did not swallow an error leaving signer unset
  4. Log/inspect whether the signer was dropped or reset between construction and submission

Example fix

// before
let client = ExecutionClient::new(config);
client.submit_order(order).await?;
// after
let client = ExecutionClient::new(config);
client.connect(signer_credentials).await?;
assert!(client.has_signer());
client.submit_order(order).await?;
Defensive patterns

Strategy: validation

Validate before calling

if !client.has_signer() {
    anyhow::bail!("call client.connect(credentials) before submit_order");
}

Type guard

fn signer_ready(client: &ExecutionClient) -> bool {
    client.has_signer()
}

Prevention

When it happens

Trigger: Calling submit_order (which reaches prepare_swap) on a client constructed without a signer, or after the signer was removed/reset; the client reached ensure_transaction_ready but self.signer is still None.

Common situations: Forgetting to call connect() before submit_order; constructing the client in read-only/market-data mode and then trading; a config file missing the private key/keystore entry; signer initialization failing silently earlier and leaving signer None.

Related errors


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

Appendix: source

Thrown at crates/adapters/blockchain/src/execution/client.rs:1718

                        "No `quote_spend_limits` entry for BUY token pair {token_in} -> {token_out}"
                    )
                })?;

                if amount_in > ceiling.max_amount {
                    anyhow::bail!(
                        "BUY quote amount {amount_in} exceeds the configured `quote_spend_limits` maximum {} for {token_in} -> {token_out}",
                        ceiling.max_amount
                    );
                }
                (amount_in, base_amount)
            }
        };
        let min_amount_out = derive_min_amount_out(quoted_amount_out, slippage_bps)?;

        self.ensure_transaction_ready(TransactionPurpose::Swap)?;

        if self.signer.is_none() {
            anyhow::bail!("Signer not initialized; connect the client first");
        }

        let pool_address = pool.address;
        let factory = self.uniswap_v3_factory()?;
        anyhow::ensure!(
            pool.dex.factory == factory,
            "Pool {instrument_id} references factory {}, expected registered factory {factory}",
            pool.dex.factory
        );

        Ok(SwapPlan {
            order: order.clone(),
            pool,
            quote_currency,
            instrument_id,
            pool_address,
            router: self.router_addresses[0],
            factory,

View on GitHub (pinned to 18893faf8b)