{"record":{"id":"8725248aa6678e07","repo":"nautechsystems/nautilus_trader","slug":"pool-state-at-block-has-no-ingestion-time-block","errorCode":null,"errorMessage":"Pool state at block {} has no ingestion-time block hash; refresh the profiler before execution","messagePattern":"Pool state at block (.+?) has no ingestion-time block hash; refresh the profiler before execution","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/execution/client.rs","lineNumber":3940,"sourceCode":"                .database\n                .mark_execution_event_emitted(intent.id, \"terminal\")\n                .await?;\n            executor.release_slot();\n            Ok(())\n        }\n        InclusionOutcome::Pending(message) => anyhow::bail!(message),\n    }\n}\n\nasync fn validate_swap_quote(\n    position: &BlockPosition,\n    plan: &SwapPlan,\n    max_age_blocks: u64,\n    verification: &VerificationCoordinator,\n    manifest: &BlockchainDeploymentManifest,\n) -> anyhow::Result<SwapQuoteAnchors> {\n    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,","sourceCodeStart":3922,"sourceCodeEnd":3958,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/execution/client.rs#L3922-L3958","documentation":"Before executing a swap, the library anchors the quote to the profiler's ingestion-time pool-state snapshot, which must record the block hash of the block it was taken at. If the snapshot row has no block hash, the quote cannot be verified against canonical chain state, so execution refuses to proceed and asks the user to refresh the profiler data.","triggerScenarios":"Calling the quote-anchor validation with a profiler pool-state row whose block_hash field is NULL/empty (position.block_hash is None) while preparing a SwapPlan.","commonSituations":"Profiler snapshots ingested by an older indexer version that didn't persist block hashes; partially written snapshot rows; running execution against a stale or hand-built dataset; DB schema change/migration that dropped the column values.","solutions":["Refresh the profiler so the pool-state snapshot at the given block is re-ingested with its block hash.","Re-run the ingestion/indexer job covering that block to backfill block_hash.","Pin execution to a newer snapshot block that has a valid hash.","Check that the indexer version writes block_hash for every pool-state row."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if position.block_hash.as_deref().map_or(true, |h| h.is_empty()) {\n    // refresh the profiler before building a SwapPlan on this snapshot\n    refresh_profiler(position.number)?;\n}","typeGuard":"fn has_ingestion_block_hash(position: &PoolStatePosition) -> bool {\n    position.block_hash.as_deref().map_or(false, |h| !h.is_empty())\n}","tryCatchPattern":"match build_quote_anchors(position, plan, max_age, verification, manifest) {\n    Ok(anchors) => execute(anchors),\n    Err(e) if e.to_string().contains(\"no ingestion-time block hash\") => {\n        refresh_profiler(position.number)?;\n        retry();\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Use an indexer version that always persists block_hash with pool-state rows.","Refuse to execute on snapshots missing block hash at plan-build time.","Schedule profiler refreshes before execution windows."],"tags":["stale-data","profiler","missing-field","blockchain"],"backgroundTag":"empty-required-field","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"}