nautechsystems/nautilus_trader · critical
Verified chain ID does not match the transaction chain
Error message
Verified chain ID does not match the transaction chain
What it means
Before signing, the client re-verifies the chain ID via its verification provider and requires it to equal the transaction's expected chain ID. A mismatch means the node/wallet context the transaction targets differs from the verified chain, so signing is refused to prevent replay or cross-chain mistakes.
Source
Thrown at crates/adapters/blockchain/src/execution/client.rs:2295
)]
async fn prepare_and_sign_with_anchors(
&self,
intent_id: i64,
created_block: u64,
to: Address,
value: U256,
input: Bytes,
swap_anchors: Option<&SwapQuoteAnchors>,
authorization: Option<&TransactionAuthorization>,
decision_header: Option<Verified<VerifiedBlockHeader>>,
) -> anyhow::Result<PreparedTransaction> {
let expected_chain_id = u64::from(self.chain_id);
let chain_id_verification = required_verification(
self.verification.verify_chain_id().await,
"pre-sign chain ID",
)?;
let actual_chain_id = chain_id_verification.value;
anyhow::ensure!(
actual_chain_id == expected_chain_id,
"Verified chain ID does not match the transaction chain"
);
let decision_header_verification = if let Some(anchors) = swap_anchors {
required_verification(
self.verification.verify_block(anchors.state.number).await,
"pre-sign swap decision header reread",
)?
} else {
match decision_header {
Some(verified) => verified,
None => {
let now_unix_secs = current_unix_secs()?;
required_verification(
self.verification
.verify_decision_header(now_unix_secs)
.await,
"pre-sign decision header",View on GitHub (pinned to 18893faf8b)
Solutions
- Align the client's configured chain_id with the network actually served by the configured RPC endpoint.
- Check the RPC URL — switch to a node on the intended chain.
- Verify no automatic provider failover silently switched chains; pin the endpoint.
- Re-verify `self.chain_id` matches the signer/wallet network and reinitialize the client if config changed.
Example fix
// before: client on testnet RPC but chain_id set to mainnet // chain_id: 1, rpc: https://sepolia.infura.io let client = ExecutionClient::new(chain_id=1, rpc=SEPOLIA_URL)?; // after let client = ExecutionClient::new(chain_id=11155111, rpc=SEPOLIA_URL)?;
Defensive patterns
Strategy: validation
Validate before calling
let node_chain_id = provider.get_chain_id().await?; assert_eq!(node_chain_id, client.chain_id(), "RPC chain mismatch with client config");
Try / catch
match result { Err(e) if e.to_string().contains("Verified chain ID does not match") => { fail_fast_and_reconfigure_rpc(e); } Ok(v) => v } Prevention
- Verify RPC endpoint chain ID at client startup
- Avoid provider failover across different chains
- Keep chain_id config and signer network in sync
When it happens
Trigger: During the pre-sign check, `verification.verify_chain_id()` returns a chain ID different from `self.chain_id` (u64) used for the transaction — e.g. the RPC endpoint serves a different network than configured.
Common situations: RPC URL points to mainnet while client configured for a testnet (or vice versa); provider failover switched to a node on another chain; chain_id config value stale after a fork or network rename.
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
- Router {router} is not in the configured `router_addresses`
- Token {token} is not an input token in the configured `allow
- Verification chain anchor ID does not match the configured c
- Persisted transaction row chain ID {} does not match configu
- Chain ID mismatch at connect: expected {expected_chain_id},
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/ffcbb9595886b3fd.
Report an issue: GitHub.