{"record":{"id":"2d0bdbbe9d46f55e","repo":"nautechsystems/nautilus_trader","slug":"pool-state-block-changed-from-to-refresh","errorCode":null,"errorMessage":"Pool state block {} changed from {} to {}; refresh the profiler before execution","messagePattern":"Pool state block (.+?) changed from (.+?) to (.+?); refresh the profiler before execution","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/execution/client.rs","lineNumber":3957,"sourceCode":"    let block_hash = position.block_hash.as_deref().ok_or_else(|| {\n        anyhow::anyhow!(\n            \"Pool state at block {} has no ingestion-time block hash; refresh the profiler before execution\",\n            position.number\n        )\n    })?;\n    let expected_block_hash = B256::from_str(block_hash)\n        .with_context(|| format!(\"Invalid profiler block hash {block_hash}\"))?;\n    let now_unix_secs = current_unix_secs()?;\n    let head = verified_value(\n        verification.verify_decision_header(now_unix_secs).await,\n        \"swap decision header\",\n    )?;\n    validate_quote_age(position.number, head.number, max_age_blocks)?;\n    let canonical_block = verified_value(\n        verification.verify_block(position.number).await,\n        \"profiler watermark header\",\n    )?;\n    anyhow::ensure!(\n        canonical_block.hash == expected_block_hash,\n        \"Pool state block {} changed from {} to {}; refresh the profiler before execution\",\n        position.number,\n        expected_block_hash,\n        canonical_block.hash\n    );\n\n    let snapshot_transaction = position.transaction_index == BLOCK_SCOPED_SNAPSHOT_INDEX;\n    let snapshot_log = position.log_index == BLOCK_SCOPED_SNAPSHOT_INDEX;\n    anyhow::ensure!(\n        snapshot_transaction == snapshot_log,\n        \"Pool state at block {} has an invalid partial snapshot watermark\",\n        position.number\n    );\n\n    if snapshot_transaction {\n        let snapshot_hash = B256::from_str(&position.transaction_hash)\n            .with_context(|| \"Invalid block-scoped snapshot hash\")?;","sourceCodeStart":3939,"sourceCodeEnd":3975,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/execution/client.rs#L3939-L3975","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Refresh the profiler so pool-state snapshots are re-ingested against the current canonical chain.","Verify the RPC endpoint and chain id match the deployment manifest (no fork/devnet/mainnet mix-up).","Wait for the reorg to settle and retry execution once the profiler watermark is updated.","Compare expected vs canonical hashes from the message to confirm whether it's a reorg or data corruption."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"let canonical = verification.verify_block(position.number).await?;\nif canonical.hash != expected_block_hash {\n    // abort this attempt; refresh the profiler before retrying\n    anyhow::bail!(\"block {} reorganized at execution time\", position.number);\n}","typeGuard":null,"tryCatchPattern":"match build_quote_anchors(...).await {\n    Ok(anchors) => execute(anchors),\n    Err(e) if e.to_string().contains(\"changed from\") => {\n        refresh_profiler().await?; // reorg or stale data\n        retry_with_backoff();\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Pin execution and verification to a single consistent RPC endpoint/chain id.","Refresh the profiler shortly before execution so watermarks are near head.","Track reorg events and pause execution while they are in progress."],"tags":["blockchain","reorg","stale-data","consistency-check"],"backgroundTag":"checksum-mismatch","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}