nautechsystems/nautilus_trader · critical

Signer address {} derived from '{}' does not match configure

Error message

Signer address {} derived from '{}' does not match configured wallet address {}

What it means

At connect(), the signer private key is read from the environment variable named by signer_private_key_env, parsed, and its derived address must equal the configured wallet_address. A mismatch aborts the connection: the system refuses to trade with a key that is not the account the rest of the configuration (balances, allowances, wallet address) refers to.

Source

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

        }

        // Load the signer key from the configured environment variable; the key is never
        // logged, serialized, or stored in configuration
        let private_key = std::env::var(&self.config.signer_private_key_env).map_err(|_| {
            anyhow::anyhow!(
                "Signer private key environment variable '{}' is not set",
                self.config.signer_private_key_env
            )
        })?;
        let signer = PrivateKeySigner::from_str(private_key.trim()).map_err(|_| {
            anyhow::anyhow!(
                "Signer private key in '{}' is not a valid hex private key",
                self.config.signer_private_key_env
            )
        })?;

        if signer.address() != self.wallet_address {
            anyhow::bail!(
                "Signer address {} derived from '{}' does not match configured wallet address {}",
                signer.address(),
                self.config.signer_private_key_env,
                self.wallet_address
            );
        }

        self.signer = Some(signer);

        if self.cache.has_database()
            && let Err(e) = self.reconcile_unresolved_execution().await
        {
            self.signer = None;
            return Err(e);
        }

        if let Err(e) = self.refresh_wallet_balances().await {
            self.signer = None;

View on GitHub (pinned to 2114cf6f76)

Solutions

  1. Determine the address of the key currently in the env var (e.g. cast wallet address --private-key ...) and set wallet_address in config to that value
  2. Or update the environment variable to hold the key that controls the configured wallet_address
  3. Pin the exact env var name per environment in deployment manifests so the wrong key cannot leak across environments

Example fix

# before: env holds test key, config expects mainnet wallet
# SIGNER_PRIVATE_KEY=0x<testnet-key>  wallet_address = 0x<mainnet-wallet>

# after: key and config address match
export SIGNER_PRIVATE_KEY=0x<mainnet-key>   # cast wallet address -> 0x<mainnet-wallet>
# config: wallet_address = 0x<mainnet-wallet>
Defensive patterns

Strategy: try-catch

Validate before calling

// At startup, prove key/address pairing before connecting the client
let key = std::env::var(&config.signer_private_key_env)?;
let signer = PrivateKeySigner::from_str(key.trim())?;
anyhow::ensure!(
    signer.address() == config.wallet_address,
    "key in '{}' controls {}, config expects {}",
    config.signer_private_key_env, signer.address(), config.wallet_address
);

Try / catch

match client.connect().await {
    Err(e) if e.to_string().contains("does not match configured wallet") => {
        // Secrets/coordination issue: page the operator; do not guess which side to change
        fatal!("signer/wallet mismatch: {e}");
    }
    other => other,
}

Prevention

When it happens

Trigger: connect() with SIGNER_PRIVATE_KEY-style env var holding a key whose address differs from wallet_address in the config: key rotated in env but config not updated (or vice versa), the env var name resolving to a different environment's key, or a copy/paste of a test key into a mainnet config.

Common situations: Deploying the same config template to multiple environments with per-environment keys; CI and local shells exporting different keys; wallet address taken from an explorer for the wrong account; leading/trailing whitespace is handled (the key is trimmed) but a wrong-length or wrong-key value is not.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@2114cf6f76 (2026-08-21). Data as JSON: /api/errors/6619e12ea63345f3. Report an issue: GitHub.