{"record":{"id":"0b4b44ffbd611939","repo":"nautechsystems/nautilus_trader","slug":"failed-to-batch-insert-into-pool-flash-event-table","errorCode":null,"errorMessage":"Failed to batch insert into pool_flash_event table: {e}","messagePattern":"Failed to batch insert into pool_flash_event table: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/cache/database.rs","lineNumber":1861,"sourceCode":"           \",\n        )\n        .bind(&chain_ids[..])\n        .bind(&dex_names[..])\n        .bind(&pool_identifiers[..])\n        .bind(&blocks[..])\n        .bind(&transaction_hashes[..])\n        .bind(&transaction_indices[..])\n        .bind(&log_indices[..])\n        .bind(&senders[..])\n        .bind(&recipients[..])\n        .bind(&amount0s[..])\n        .bind(&amount1s[..])\n        .bind(&paid0s[..])\n        .bind(&paid1s[..])\n        .execute(&self.pool)\n        .await\n        .map(|_| ())\n        .map_err(|e| anyhow::anyhow!(\"Failed to batch insert into pool_flash_event table: {e}\"))\n    }\n\n    /// Inserts multiple pool fee-protocol update events in a single database operation using UNNEST.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if the database operation fails.\n    pub async fn add_pool_fee_protocol_updates_batch(\n        &self,\n        chain_id: u32,\n        updates: &[PoolFeeProtocolUpdate],\n    ) -> anyhow::Result<()> {\n        if updates.is_empty() {\n            return Ok(());\n        }\n\n        // Prepare vectors for each column\n        let len = updates.len();","sourceCodeStart":1843,"sourceCodeEnd":1879,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/cache/database.rs#L1843-L1879","documentation":"Raised when a batched UNNEST INSERT of pool flash events (with paid0/paid1 amounts) into the `pool_flash_event` table fails. The sqlx execution error is wrapped in anyhow with this message; the driver error text follows the prefix. The flash-event batch is not persisted when this fires.","triggerScenarios":"Executing the multi-row flash-event insert (`.bind(&amount1s[..])`, `.bind(&paid0s[..])`, `.bind(&paid1s[..])`, `.execute(&self.pool)`) when Postgres rejects it: constraint violation, type coercion failure on amount strings, array-length mismatch, or connection failure.","commonSituations":"Amount strings exceeding the numeric column's precision after a schema change; mismatched vector lengths when the event batch is assembled; dead pool connections after idle timeouts; concurrent writers causing unique/PK conflicts.","solutions":["Inspect the wrapped `{e}` suffix for the underlying sqlx/PostgreSQL error","Confirm all bound arrays (identifiers, blocks, amounts, paid0s, paid1s, ...) share the same length","Run schema migrations so `pool_flash_event` columns match the bound fields","Check database connectivity and pool configuration","Add ON CONFLICT handling or deduplicate the batch if unique-constraint errors appear"],"exampleFix":"// before\n.map_err(|e| anyhow::anyhow!(\"Failed to batch insert into pool_flash_event table: {e}\"))\n// after: guard against length mismatch before execution\nassert_eq!(paid0s.len(), paid1s.len());\n.map_err(|e| anyhow::anyhow!(\"Failed to batch insert into pool_flash_event table (rows={}): {e}\", paid0s.len()))","handlingStrategy":"try-catch","validationCode":"fn validate_flash_batch(rows: &[PoolFlashEvent]) -> anyhow::Result<()> {\n    anyhow::ensure!(!rows.is_empty(), \"empty flash batch\");\n    anyhow::ensure!(rows.iter().all(|r| !r.transaction_hash.is_empty()), \"missing tx hash\");\n    Ok(())\n}","typeGuard":"fn is_non_empty(s: &Option<String>) -> bool { s.as_ref().map_or(false, |v| !v.is_empty()) }","tryCatchPattern":"if let Err(e) = insert_pool_flash_events(&events).await {\n    tracing::error!(\"flash batch insert failed: {e:#}\");\n    if is_transient(&e) { retry_with_backoff(&events).await?; }\n}","preventionTips":["Check amounts fit the numeric column precision before binding","Run migrations before starting indexing runs","Deduplicate events per (block, tx, log index) to avoid unique conflicts","Health-check the pool before large batch writes"],"tags":["database","postgres","sqlx","batch-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"}