{"record":{"id":"e9303753143540e2","repo":"nautechsystems/nautilus_trader","slug":"cannot-advance-an-rpc-profiler-without-a-snapshot","errorCode":null,"errorMessage":"cannot advance an RPC profiler without a snapshot watermark","messagePattern":"cannot advance an RPC profiler without a snapshot watermark","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/data/core.rs","lineNumber":1609,"sourceCode":"    }\n\n    /// Advances an RPC-hydrated profiler to a later checkpoint.\n    ///\n    /// The profiler must come from [`Self::bootstrap_pool_profiler_from_rpc_snapshot`] or an earlier\n    /// call to this method. This keeps one command incremental without trusting an unproven stored\n    /// snapshot as the topology source.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if the profiler has no RPC snapshot watermark, the target precedes that\n    /// watermark, event streaming fails, or RPC hydration fails.\n    pub async fn advance_pool_profiler_from_rpc_snapshot(\n        &mut self,\n        profiler: PoolProfiler,\n        to_block: u64,\n    ) -> anyhow::Result<(PoolProfiler, bool)> {\n        let from_position = profiler.last_processed_event.clone().ok_or_else(|| {\n            anyhow::anyhow!(\"cannot advance an RPC profiler without a snapshot watermark\")\n        })?;\n\n        if to_block < from_position.number {\n            anyhow::bail!(\n                \"cannot advance RPC profiler from block {} to earlier block {to_block}\",\n                from_position.number\n            );\n        }\n\n        self.construct_pool_profiler_from_hypersync_rpc(profiler, Some(from_position), to_block)\n            .await\n    }\n\n    async fn seed_pool_profiler_from_latest_snapshot(\n        &self,\n        pool: &SharedPool,\n        to_block: u64,\n    ) -> anyhow::Result<(PoolProfiler, Option<BlockPosition>)> {","sourceCodeStart":1591,"sourceCodeEnd":1627,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/data/core.rs#L1591-L1627","documentation":"advance_pool_profiler_from_rpc_snapshot requires the incoming profiler to carry a last_processed_event watermark — the snapshot position from which RPC-derived events will be advanced to to_block. If the profiler has no watermark (never snapshotted or built only from live data), advancement is impossible and this invariant error is returned.","triggerScenarios":"Passing a fresh PoolProfiler whose last_processed_event is None (built locally, not deserialized from a snapshot store) into advance_pool_profiler_from_rpc_snapshot.","commonSituations":"Calling the RPC advancement path with a profiler constructed in-memory instead of one restored from persisted profiler state; version drift where older stored snapshots lack the watermark field.","solutions":["Initialize the profiler from a persisted snapshot that includes last_processed_event before calling advance.","If no snapshot exists, use the full bootstrap path (sync_pool_events / bootstrap_latest_pool_profiler) instead of the RPC advancement path.","Check that the state store round-trips last_processed_event correctly when saving/loading the profiler.","Guard the call site: only advance when profiler.last_processed_event.is_some()."],"exampleFix":"// before\nlet (profiler, _) = core.advance_pool_profiler_from_rpc_snapshot(new_profiler, head).await?;\n\n// after\nif new_profiler.last_processed_event.is_none() {\n    let (new_profiler, _) = core.bootstrap_latest_pool_profiler(...).await?;\n}\nlet (profiler, _) = core.advance_pool_profiler_from_rpc_snapshot(new_profiler, head).await?;","handlingStrategy":"validation","validationCode":"// guard before calling the RPC advancement path\nif profiler.last_processed_event.is_none() {\n    return Err(anyhow::anyhow!(\n        \"profiler has no snapshot watermark; run bootstrap_latest_pool_profiler first\"\n    ));\n}","typeGuard":"fn has_watermark(p: &PoolProfiler) -> bool {\n    p.last_processed_event.is_some()\n}","tryCatchPattern":null,"preventionTips":["Only advance profilers restored from persisted snapshots that include last_processed_event","Use the bootstrap path for fresh/in-memory profilers","Verify the state store round-trips the watermark field"],"tags":["pool-profiler","snapshot","precondition","blockchain"],"backgroundTag":"missing-required-argument","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}