{"record":{"id":"be9ede3cbaf57a5a","repo":"nautechsystems/nautilus_trader","slug":"failed-to-write-pool-liquidity-update-data-e","errorCode":null,"errorMessage":"Failed to write pool liquidity update data: {e}","messagePattern":"Failed to write pool liquidity update data: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/cache/copy.rs","lineNumber":618,"sourceCode":"        row_data.write_all(&(owner_bytes.len() as i32).to_be_bytes())?;\n        row_data.write_all(&owner_bytes)?;\n\n        write_copy_numeric(&mut row_data, update.position_liquidity);\n        write_copy_numeric(&mut row_data, update.amount0);\n        write_copy_numeric(&mut row_data, update.amount1);\n\n        let tick_lower_bytes = update.tick_lower.to_be_bytes();\n        row_data.write_all(&(tick_lower_bytes.len() as i32).to_be_bytes())?;\n        row_data.write_all(&tick_lower_bytes)?;\n\n        let tick_upper_bytes = update.tick_upper.to_be_bytes();\n        row_data.write_all(&(tick_upper_bytes.len() as i32).to_be_bytes())?;\n        row_data.write_all(&tick_upper_bytes)?;\n\n        copy_in\n            .send(row_data)\n            .await\n            .map_err(|e| anyhow::anyhow!(\"Failed to write pool liquidity update data: {e}\"))?;\n        Ok(())\n    }\n\n    /// Inserts pool fee collect events using PostgreSQL COPY BINARY for maximum performance.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if the COPY operation fails.\n    pub async fn copy_pool_collects(\n        &self,\n        chain_id: u32,\n        collects: &[PoolFeeCollect],\n    ) -> anyhow::Result<()> {\n        if collects.is_empty() {\n            return Ok(());\n        }\n\n        let copy_statement = \"","sourceCodeStart":600,"sourceCodeEnd":636,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/cache/copy.rs#L600-L636","documentation":"write_pool_liquidity_update_binary serializes one PoolLiquidityUpdate (including tick_lower/tick_upper i32 fields) and sends it over the COPY BINARY stream; a send failure is wrapped in this message. The whole copy_pool_liquidity_updates batch aborts via `?`. As with other row writers, the cause is a dead connection or an already-aborted COPY session.","triggerScenarios":"Connection loss mid-stream, server abort of the COPY from a previously written bad row, or a serialization mismatch (field order/width) with the pool_liquidity_update column list after a schema change.","commonSituations":"Long backfills interrupted by network blips; liquidity updates written before their parent pools (earlier-row FK failure surfacing here); migrations altering the table while the writer is unchanged.","solutions":["Inspect the wrapped sqlx::Error for transport vs server-abort cause","Run copy_pools first so FK parents exist","Diff write_pool_liquidity_update_binary's writes against the COPY column list post-migration","Retry in smaller chunks to isolate the bad row"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match handler.copy_pool_liquidity_updates(chain_id, &updates).await {\n    Err(e) if e.to_string().contains(\"Failed to write pool liquidity update data\") => {\n        tokio::time::sleep(Duration::from_secs(5)).await;\n        handler.copy_pool_liquidity_updates(chain_id, &updates).await?;\n    }\n    other => other?,\n}","preventionTips":["Run copy_pools before liquidity updates (FK ordering)","Verify tick field serialization (i32 big-endian, fixed width) after migrations","Chunk updates for isolated retries","Watch DB logs for early session aborts"],"tags":["postgres","copy-binary","streaming"],"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-14T05:17:10.506Z"}