nautechsystems/nautilus_trader · error

Signed transaction signer {} does not match configured walle

Error message

Signed transaction signer {} does not match configured wallet {}

What it means

In `validate_signed_transaction` (crates/adapters/blockchain/src/execution/transaction.rs:257), after decoding the persisted EIP-1559 envelope, the signer address recovered from the signature is compared to the configured wallet (`intent.signer`). The library refuses to treat a signed transaction as authorized when it was actually signed by a different key — this is a defense against replaying transactions signed by an unauthorized key under someone else's intent.

Source

Thrown at crates/adapters/blockchain/src/execution/transaction.rs:257

pub(super) fn validate_signed_transaction(
    raw_transaction: &[u8],
    intent: &SignedTransactionIntent,
) -> anyhow::Result<()> {
    let tx = decode_signed_transaction(raw_transaction)?;

    anyhow::ensure!(
        tx.hash == intent.hash,
        "Persisted transaction hash {} does not match signed transaction hash {}",
        intent.hash,
        tx.hash
    );
    anyhow::ensure!(
        intent.durable_signer == intent.signer,
        "Persisted transaction signer {} does not match configured wallet {}",
        intent.durable_signer,
        intent.signer
    );
    anyhow::ensure!(
        tx.signer == intent.signer,
        "Signed transaction signer {} does not match configured wallet {}",
        tx.signer,
        intent.signer
    );
    anyhow::ensure!(
        intent.intent_chain_id == intent.chain_id,
        "Persisted intent chain ID {} does not match configured chain ID {}",
        intent.intent_chain_id,
        intent.chain_id
    );
    anyhow::ensure!(
        intent.row_chain_id == intent.chain_id,
        "Persisted transaction row chain ID {} does not match configured chain ID {}",
        intent.row_chain_id,
        intent.chain_id
    );

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Recover the signer from the raw bytes and compare with intent.signer to confirm which key actually signed
  2. Re-sign the transaction with the configured wallet's key and re-persist the intent/raw pair
  3. Ensure the configured wallet (keystore, private key env var, provider account) is the same one used to produce the signature
  4. Verify you are passing the correct raw transaction bytes for this intent (hash check precedes this check, so bytes likely belong to another intent)

Example fix

// before: signed with a different key
let signed = signer_b.sign_tx(tx).encoded_2718();
validate_signed_transaction(&signed, &intent_for_signer_a)?; // ensure! fails
// after: sign with the configured wallet
let signed = configured_wallet.sign_tx_sync_without_keystore256(tx).encoded_2718();
validate_signed_transaction(&signed, &intent_for_signer_a)?;
Defensive patterns

Strategy: validation

Validate before calling

let decoded = decode_signed_transaction(&raw)?;
if decoded.signer != intent.signer {
    return Err(anyhow::anyhow!("raw tx signed by {}, intent requires {}", decoded.signer, intent.signer));
}

Type guard

fn signed_by_configured_wallet(tx: &DecodedSignedTransaction, intent: &SignedTransactionIntent) -> bool {
    tx.signer == intent.signer
}

Try / catch

match authenticate_payload_identity_with_signer(&raw, &intent) {
    Ok(()) => { /* proceed */ }
    Err(e) if e.to_string().contains("Signed transaction signer") => {
        // wrong key: re-sign with the configured wallet before retrying
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Passing raw signed-transaction bytes whose ECDSA signature recovers to an address different from `intent.signer` into `authenticate_payload_identity_with_signer` / `validate_signed_transaction`. Also occurs when the wallet changed between persist and replay, or the wrong raw bytes are paired with the intent.

Common situations: Configured wallet/key rotation without re-signing persisted transactions; passing a different transaction's raw bytes to the wrong intent; using a test/dev key in one environment and a production key in another; multisig or relayer signing with a hot key that differs from the configured address.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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