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
- Recover the signer from the raw bytes and compare with intent.signer to confirm which key actually signed
- Re-sign the transaction with the configured wallet's key and re-persist the intent/raw pair
- Ensure the configured wallet (keystore, private key env var, provider account) is the same one used to produce the signature
- 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
- Always sign with the wallet resolved from the same config the intent was built from
- Pair raw signed bytes with their intent atomically so bytes can't be matched to the wrong intent
- Recover the signer address immediately after signing and assert it equals the configured wallet
- Keep test/dev keys out of production signing paths
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
- Persisted transaction signer {} does not match configured wa
- Execution intent {} signed transaction {} failed authenticat
- Canonical signer-nonce transaction {} has no authenticated r
- Persisted intent chain ID {} does not match configured chain
- Signed transaction chain ID {} does not match configured cha
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/5e491ed0cd32b981.
Report an issue: GitHub.