nautechsystems/nautilus_trader · error

Pool state block {} changed from {} to {}; refresh the profi

Error message

Pool state block {} changed from {} to {}; refresh the profiler before execution

What it means

The library verifies the profiler snapshot's block hash against the canonical chain header fetched via the verification coordinator. If the canonical block at that height hashes differently, the chain reorganized (or the profiler data is wrong) between ingestion and swap decision, so execution aborts and asks for a profiler refresh. This prevents trading on quotes anchored to orphaned blocks.

Source

Thrown at crates/adapters/blockchain/src/execution/client.rs:3957

    let block_hash = position.block_hash.as_deref().ok_or_else(|| {
        anyhow::anyhow!(
            "Pool state at block {} has no ingestion-time block hash; refresh the profiler before execution",
            position.number
        )
    })?;
    let expected_block_hash = B256::from_str(block_hash)
        .with_context(|| format!("Invalid profiler block hash {block_hash}"))?;
    let now_unix_secs = current_unix_secs()?;
    let head = verified_value(
        verification.verify_decision_header(now_unix_secs).await,
        "swap decision header",
    )?;
    validate_quote_age(position.number, head.number, max_age_blocks)?;
    let canonical_block = verified_value(
        verification.verify_block(position.number).await,
        "profiler watermark header",
    )?;
    anyhow::ensure!(
        canonical_block.hash == expected_block_hash,
        "Pool state block {} changed from {} to {}; refresh the profiler before execution",
        position.number,
        expected_block_hash,
        canonical_block.hash
    );

    let snapshot_transaction = position.transaction_index == BLOCK_SCOPED_SNAPSHOT_INDEX;
    let snapshot_log = position.log_index == BLOCK_SCOPED_SNAPSHOT_INDEX;
    anyhow::ensure!(
        snapshot_transaction == snapshot_log,
        "Pool state at block {} has an invalid partial snapshot watermark",
        position.number
    );

    if snapshot_transaction {
        let snapshot_hash = B256::from_str(&position.transaction_hash)
            .with_context(|| "Invalid block-scoped snapshot hash")?;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Refresh the profiler so pool-state snapshots are re-ingested against the current canonical chain.
  2. Verify the RPC endpoint and chain id match the deployment manifest (no fork/devnet/mainnet mix-up).
  3. Wait for the reorg to settle and retry execution once the profiler watermark is updated.
  4. Compare expected vs canonical hashes from the message to confirm whether it's a reorg or data corruption.
Defensive patterns

Strategy: retry

Validate before calling

let canonical = verification.verify_block(position.number).await?;
if canonical.hash != expected_block_hash {
    // abort this attempt; refresh the profiler before retrying
    anyhow::bail!("block {} reorganized at execution time", position.number);
}

Try / catch

match build_quote_anchors(...).await {
    Ok(anchors) => execute(anchors),
    Err(e) if e.to_string().contains("changed from") => {
        refresh_profiler().await?; // reorg or stale data
        retry_with_backoff();
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: During swap quote-anchor validation, verification.verify_block(position.number) returns a block whose hash differs from the profiler snapshot's expected_block_hash for the same block number.

Common situations: A chain reorg after the profiler ingested the block; profiler pointed at a different network/fork (e.g. devnet vs mainnet RPC mix-up); stale profiler data after an intentional chain reset; wrong chain id in deployment manifest.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — 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/2d0bdbbe9d46f55e. Report an issue: GitHub.