nautechsystems/nautilus_trader · error

Persisted intent chain ID {} does not match configured chain

Error message

Persisted intent chain ID {} does not match configured chain ID {}

What it means

`validate_signed_transaction` checks that the chain ID persisted inside the intent (`intent_chain_id`) equals the chain ID the wallet/adapter was configured for (`intent.chain_id`). The library throws this when the durable intent was recorded for a different network than the one the adapter currently targets, preventing transactions intended for one chain from being replayed on another.

Source

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

    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
    );

    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
    );

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Align the adapter's configured chain_id with the chain the intents were persisted for, or vice versa
  2. Re-create the intents under the current chain configuration (do not hand-edit persisted rows)
  3. Check the chain ID in your config/env (RPC endpoint and chain_id setting must agree) before processing persisted transactions
  4. If rows were copied from another environment, purge or migrate them explicitly rather than replaying

Example fix

// before (config drifted from persisted intent)
// config: chain_id = 42161 (Arbitrum), row: intent_chain_id = 1 (mainnet)
validate_signed_transaction(&raw, &intent)?; // ensure! fails
// after: run the adapter against the chain the intent was created for
// config: chain_id = 1, row: intent_chain_id = 1
validate_signed_transaction(&raw, &intent)?;
Defensive patterns

Strategy: validation

Validate before calling

if intent.intent_chain_id != intent.chain_id {
    return Err(anyhow::anyhow!(
        "intent chain {} != configured chain {}",
        intent.intent_chain_id, intent.chain_id
    ));
}

Type guard

fn intent_targets_configured_chain(intent: &SignedTransactionIntent) -> bool {
    intent.intent_chain_id == intent.chain_id
}

Try / catch

match authenticate_payload_identity_with_signer(&raw, &intent) {
    Ok(()) => { /* proceed */ }
    Err(e) if e.to_string().contains("Persisted intent chain ID") => {
        // chain config drifted: halt replay and re-create intents for the current chain
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling `authenticate_payload_identity_with_signer` / `validate_signed_transaction` with an intent where `intent.intent_chain_id != intent.chain_id`. This is a pre-signature check on the persisted intent itself — no transaction bytes need to be malformed.

Common situations: Pointing the adapter at a different network (e.g. mainnet vs Sepolia vs an L2 like Arbitrum) after intents were persisted against the old chain; a config/env change of the chain ID while old database rows remain; copying database state between environments with different chain configurations.

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


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