nautechsystems/nautilus_trader · error
Signed transaction chain ID {} does not match configured cha
Error message
Signed transaction chain ID {} does not match configured chain ID {} What it means
Finally, `validate_signed_transaction` compares the chain ID actually encoded in the signed EIP-1559 transaction (`tx.chain_id`, recovered from the raw bytes) against the configured chain ID. EIP-155 replay protection bakes the chain ID into the signature, so a mismatch means the transaction was signed for a different network and must never be broadcast by this adapter.
Source
Thrown at crates/adapters/blockchain/src/execution/transaction.rs:276
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
);
anyhow::ensure!(
tx.chain_id == u64::from(intent.chain_id),
"Signed transaction chain ID {} does not match configured chain ID {}",
tx.chain_id,
intent.chain_id
);
anyhow::ensure!(
tx.nonce == intent.nonce,
"Signed transaction nonce {} does not match persisted nonce {}",
tx.nonce,
intent.nonce
);
anyhow::ensure!(
tx.to == intent.to,
"Signed transaction destination {} does not match persisted destination {}",
tx.to,
intent.to
);
anyhow::ensure!(View on GitHub (pinned to 18893faf8b)
Solutions
- Re-sign the transaction with the wallet/provider bound to the configured chain so the EIP-155 chain ID matches
- Align the adapter's configured chain_id with the chain the transaction was actually signed for, then re-persist intent + bytes together
- Verify the signing provider/keystore is connected to the intended network before signing
- Regenerate intent and signed bytes as an atomic pair whenever the chain configuration changes
Example fix
// before: tx signed for chain 1, adapter configured for 42161 let signed = provider_chain1.sign(tx).encoded_2718(); validate_signed_transaction(&signed, &intent_chain_42161)?; // ensure! fails // after: sign against the configured chain let signed = provider_arbitrum.sign(tx).encoded_2718(); // tx.chain_id = 42161 validate_signed_transaction(&signed, &intent_chain_42161)?;
Defensive patterns
Strategy: validation
Validate before calling
let decoded = decode_signed_transaction(&raw)?;
if decoded.chain_id != Some(u64::from(intent.chain_id)) {
return Err(anyhow::anyhow!(
"tx chain {:?} != configured chain {}",
decoded.chain_id, intent.chain_id
));
} Type guard
fn signed_for_configured_chain(tx: &DecodedSignedTransaction, intent: &SignedTransactionIntent) -> bool {
tx.chain_id == Some(u64::from(intent.chain_id))
} Try / catch
match authenticate_payload_identity_with_signer(&raw, &intent) {
Ok(()) => { /* proceed */ }
Err(e) if e.to_string().contains("Signed transaction chain ID") => {
// EIP-155 mismatch: re-sign on the configured chain; do not broadcast
}
Err(e) => return Err(e),
} Prevention
- Sign only through a provider/wallet bound to the configured chain
- Assert the signing provider's get_chain_id() matches config before every signing batch
- Regenerate intent and signed bytes together whenever chain configuration changes
- Never relay transactions signed by external services without re-checking their embedded chain ID
When it happens
Trigger: Calling `authenticate_payload_identity_with_signer` / `validate_signed_transaction` with signed bytes whose embedded `tx.chain_id` differs from `u64::from(intent.chain_id)` — e.g. a transaction signed for mainnet while the adapter is configured for an L2, or vice versa.
Common situations: Signing with a wallet/provider bound to the wrong network; switching the adapter's chain configuration after signing; relaying transactions produced by another service configured for a different chain; EIP-155 signatures from testnet keys reaching a mainnet-configured pipeline.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Persisted intent chain ID {} does not match configured chain
- Chain ID mismatch at connect: expected {expected_chain_id},
- Verification chain anchor ID does not match the configured c
- Persisted transaction row chain ID {} does not match configu
- Verified chain ID does not match the transaction chain
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/7b5a14febba46c93.
Report an issue: GitHub.