{"record":{"id":"0fbee6bd89bfc471","repo":"nautechsystems/nautilus_trader","slug":"failed-to-finish-copy-operation-e","errorCode":null,"errorMessage":"Failed to finish COPY operation: {e}","messagePattern":"Failed to finish COPY operation: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/cache/copy.rs","lineNumber":83,"sourceCode":"            .map_err(|e| anyhow::anyhow!(\"Failed to start COPY operation: {e}\"))?;\n\n        // Write binary header\n        self.write_copy_header(&mut copy_in).await?;\n\n        // Write each block as binary data\n        for block in blocks {\n            self.write_block_binary(&mut copy_in, chain_id, block)\n                .await?;\n        }\n\n        // Write binary trailer\n        self.write_copy_trailer(&mut copy_in).await?;\n\n        // Finish the COPY operation\n        copy_in\n            .finish()\n            .await\n            .map_err(|e| anyhow::anyhow!(\"Failed to finish COPY operation: {e}\"))?;\n\n        Ok(())\n    }\n\n    /// Inserts tokens 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_tokens(&self, chain_id: u32, tokens: &[Token]) -> anyhow::Result<()> {\n        if tokens.is_empty() {\n            return Ok(());\n        }\n\n        let copy_statement = \"\n            COPY token (\n                chain_id, address, name, symbol, decimals\n            ) FROM STDIN WITH (FORMAT BINARY)\";","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/cache/copy.rs#L65-L101","documentation":"After streaming all block rows, the adapter calls `copy_in.finish()` to commit the COPY BINARY stream and finalize the statement. If finishing fails (protocol error, dropped connection mid-stream, server-side constraint failure surfaced at completion), this error is returned. Data may be partially buffered and the COPY is aborted.","triggerScenarios":"`copy_blocks` at crates/adapters/blockchain/src/cache/copy.rs:83 writes header, all block rows, and the trailer, then `copy_in.finish().await` returns Err — typically connection drop during the stream or a server-side data/type error detected on completion.","commonSituations":"Long-running COPY interrupted by network timeout or Postgres idle/connection limits; binary-encoded values rejected by the server at finalize (bad types, constraint violation); pool connection reclaimed mid-operation.","solutions":["Check the wrapped `e` for server-reported causes (invalid binary representation, constraint violation) and fix the serialized row data.","Verify network stability and Postgres timeouts for long COPY streams; increase statement/idle timeouts if needed.","Ensure trailer and row encodings match the declared COPY BINARY column types exactly.","Retry the whole `copy_blocks` call; COPY is atomic per statement so partial data is rolled back."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// pre-check column types so binary encodings match:\n// SELECT column_name, data_type FROM information_schema.columns WHERE table_name = 'blocks';","typeGuard":null,"tryCatchPattern":"if let Err(e) = copy_blocks(&cache, &blocks).await {\n    if e.to_string().contains(\"Failed to finish COPY\") {\n        log::error!(\"COPY stream failed at finalize: {e}; retrying batch atomically\");\n        retry_with_backoff(|| copy_blocks(&cache, &blocks), 3).await?;\n    } else { return Err(e); }\n}","preventionTips":["Keep COPY batches small enough to finish within network/DB timeouts.","Ensure write_*_binary encodings exactly match declared column types.","Enable TCP keepalives for long streams.","Check Postgres logs when finalize fails to find server-side causes."],"tags":["postgres","database","copy","bulk-insert"],"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"}