nautechsystems/nautilus_trader · error · anyhow::Error

Execution payload deployment ID does not match this database

Error message

Execution payload deployment ID does not match this database

What it means

This ensure! verifies that the deployment_id stored inside the loaded ExecutionPayloadState matches the deployment_id derived from the configured payload keys. The cache database is deployment-scoped; a payload from a different deployment must not be loaded. It prevents cross-deployment data confusion.

Source

Thrown at crates/adapters/blockchain/src/cache/database.rs:7489

) -> anyhow::Result<ExecutionPayloadState> {
    Ok(ExecutionPayloadState {
        deployment_id: row.try_get("deployment_id")?,
        protocol_version: row.try_get("protocol_version")?,
        operation: row.try_get("operation")?,
        active_key_id: row.try_get("active_key_id")?,
    })
}

fn validate_execution_payload_state(
    state: &ExecutionPayloadState,
    keys: &PayloadKeySet,
) -> anyhow::Result<()> {
    anyhow::ensure!(
        state.protocol_version == EXECUTION_PAYLOAD_PROTOCOL_VERSION,
        "Execution payload protocol version {} is not supported",
        state.protocol_version
    );
    anyhow::ensure!(
        state.deployment_id == keys.deployment_id(),
        "Execution payload deployment ID does not match this database"
    );
    anyhow::ensure!(
        state.active_key_id.as_slice() == keys.active_key_id(),
        "Configured active payload key does not match the database active key"
    );
    Ok(())
}

async fn lock_execution_payload_operation(
    transaction: &mut Transaction<'_, Postgres>,
) -> anyhow::Result<()> {
    let lock = PgAdvisoryLock::new("nautilus:blockchain:execution-payload");
    let PgAdvisoryLockKey::BigInt(lock_key) = lock.key() else {
        unreachable!("string advisory locks use the 64-bit key space");
    };
    sqlx::query("SELECT pg_advisory_xact_lock($1)")

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Use a cache database dedicated to this deployment_id (create a new database or schema)
  2. Restore the correct deployment configuration so keys.deployment_id() matches the stored data
  3. Purge/rebuild the local cache if the old data is no longer needed
Defensive patterns

Strategy: validation

Validate before calling

if stored.deployment_id != configured_keys.deployment_id() {
    return Err("cache database belongs to a different deployment".into());
}

Prevention

When it happens

Trigger: Calling the payload load/validate path where the row's deployment_id differs from the deployment_id of the configured PayloadKeySet — e.g. reusing a cache database across two deployments.

Common situations: Copying a production cache DB into a staging environment; changing deployment configuration without a fresh database; pointing multiple deployments at one shared Postgres cache.

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/bbed819131c5a896. Report an issue: GitHub.