{"record":{"id":"2242088b61594acd","repo":"nautechsystems/nautilus_trader","slug":"failed-to-update-dex-last-synced-block-e","errorCode":null,"errorMessage":"Failed to update dex last synced block: {e}","messagePattern":"Failed to update dex last synced block: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/cache/database.rs","lineNumber":1462,"sourceCode":"        &self,\n        chain_id: u32,\n        dex: &DexType,\n        block_number: u64,\n    ) -> anyhow::Result<()> {\n        sqlx::query(\n            \"\n            UPDATE dex\n            SET last_full_sync_pools_block_number = $3\n            WHERE chain_id = $1 AND name = $2\n            \",\n        )\n        .bind(chain_id as i32)\n        .bind(dex.to_string())\n        .bind(block_number as i64)\n        .execute(&self.pool)\n        .await\n        .map(|_| ())\n        .map_err(|e| anyhow::anyhow!(\"Failed to update dex last synced block: {e}\"))\n    }\n\n    /// Updates the last synced block number for a pool.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if the database update fails.\n    pub async fn update_pool_last_synced_block(\n        &self,\n        chain_id: u32,\n        dex: &DexType,\n        pool_identifier: &PoolIdentifier,\n        block_number: u64,\n    ) -> anyhow::Result<()> {\n        sqlx::query(\n            \"\n            UPDATE pool\n            SET last_full_sync_block_number = $4","sourceCodeStart":1444,"sourceCodeEnd":1480,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/cache/database.rs#L1444-L1480","documentation":"Wraps a sqlx error from the UPDATE statement that persists the last synced block number for a DEX on a given chain. The library throws it whenever the upsert of the DEX sync checkpoint cannot complete. Until it succeeds, resume-from-checkpoint logic will fall back to an older block.","triggerScenarios":"Calling `update_dex_last_synced_block(chain_id, dex, block_number)` when the pool connection fails, the target table is missing (migration not applied), a unique/foreign key constraint is violated, or the database is read-only.","commonSituations":"Fresh environment with unrun migrations; read-replica used for writes; database connection dropped after long sync runs; block_number exceeding i64 range (practically impossible for chains).","solutions":["Run database migrations to ensure the DEX sync checkpoint table exists","Verify the app writes to the primary, not a read-only replica","Check the underlying sqlx error message for constraint/connection details","Retry the update; transient connection errors are common after long-running syncs"],"exampleFix":"// before\n.map_err(|e| anyhow::anyhow!(\"Failed to update dex last synced block: {e}\"))\n// after\n.map_err(|e| anyhow::anyhow!(\"Failed to update dex last synced block (chain={chain_id}, dex={dex}): {e}\"))","handlingStrategy":"retry","validationCode":"// Ensure checkpoint table exists before writing\nsqlx::query(\"SELECT 1 FROM dex_sync_checkpoints LIMIT 1\").fetch_optional(&pool).await?;","typeGuard":null,"tryCatchPattern":"match update_dex_last_synced_block(chain_id, dex, block).await {\n    Ok(_) => {}\n    Err(e) if is_transient(&e) => retry_with_backoff(|| update_dex_last_synced_block(chain_id, dex, block)).await?,\n    Err(e) => return Err(e),\n}","preventionTips":["Run migrations at deployment start","Write checkpoints to the primary database, never a replica","Retry transient errors after long sync runs"],"tags":["database","sqlx","write-failure","sync-checkpoint"],"backgroundTag":"database-write-failed","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"}