{"record":{"id":"e3a8f2fc5e946b9c","repo":"nautechsystems/nautilus_trader","slug":"failed-to-persist-migration-evidence-e","errorCode":null,"errorMessage":"Failed to persist migration evidence: {e}","messagePattern":"Failed to persist migration evidence: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/cache/database.rs","lineNumber":4362,"sourceCode":"                            )\n                            \",\n                        )\n                        .bind(record.intent_id)\n                        .bind(nonce)\n                        .bind(decision.read_class)\n                        .bind(height_start)\n                        .bind(height_end)\n                        .bind(bootstrap.manifest_version)\n                        .bind(bootstrap.manifest_digest)\n                        .bind(bootstrap.provider_ids)\n                        .bind(bootstrap.operator_ids)\n                        .bind(bootstrap.failure_domain_ids)\n                        .bind(&decision.normalized_value_digest)\n                        .bind(format!(\"migration:{}:{index}\", record.intent_id))\n                        .execute(&mut *transaction)\n                        .await\n                        .map_err(|e| {\n                            anyhow::anyhow!(\"Failed to persist migration evidence: {e}\")\n                        })?;\n                    }\n                }\n            }\n            0\n        };\n\n        sqlx::query(\n            \"\n            INSERT INTO execution_verified_finalized_header (\n                chain_id, wallet_address, number, hash, parent_hash, timestamp,\n                base_fee_per_gas, manifest_digest\n            )\n            VALUES ($1, $2, $3, $4, $5, $6, $7, $8)\n            ON CONFLICT (chain_id, wallet_address, number) DO NOTHING\n            \",\n        )\n        .bind(chain_id)","sourceCodeStart":4344,"sourceCodeEnd":4380,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/cache/database.rs#L4344-L4380","documentation":"This error wraps any sqlx failure that occurs while inserting a row into the `execution_verification_decision` table during migration of prior execution records. The migration routine replays each recorded decision (read class, height range, normalized value digest, etc.) as an 'migration'-classified evidence row inside a transaction; if that INSERT fails — schema mismatch, constraint violation, type conversion, or connection loss — the underlying sqlx error is wrapped via anyhow::anyhow! with this message and the whole migration transaction aborts.","triggerScenarios":"Calling the migration/bootstrap path that persists `record.decisions` when: the `execution_verification_decision` table is missing or has a different schema (stale migration state), a bound value violates a NOT NULL/UNIQUE/FK constraint (e.g. intent_id not yet inserted, null normalized_value_digest), height values fall outside i64 range, or the PostgreSQL connection drops mid-transaction.","commonSituations":"Running the blockchain cache adapter against a database whose schema was created by an older version of the crate; migrating a record with decision rows referencing an intent that failed its own INSERT earlier in the transaction; DB connectivity blips or connection-pool exhaustion during long migrations; misconfigured `database_url` pointing at the wrong database.","solutions":["Run the latest schema migrations for this crate so `execution_verification_decision` matches the columns the INSERT expects (intent_id, nonce, decision_class, read_class, height_start, height_end, manifest_version, manifest_digest, provider_ids, operator_ids, failure_domain_ids, response_class, normalized_value_digest, nonce_revision, outcome, transition_key).","Inspect the wrapped sqlx error after the colon — it names the exact column/constraint that failed (e.g. duplicate transition_key, null value, FK violation on intent_id).","Verify the intent record was inserted successfully in the same transaction before its decisions; fix ordering or data in the migration source record.","Ensure the decision's height_start/height_end and nonce fit in i64 (u64 values above i64::MAX must be rejected before migration).","Check database connectivity, pool limits, and statement timeouts; retry the migration after the transient issue is resolved — the transaction rolls back atomically."],"exampleFix":"// before\n.execute(&mut *transaction)\n.await\n.map_err(|e| {\n    anyhow::anyhow!(\"Failed to persist migration evidence: {e}\")\n})?;\n\n// after — surface constraint details and context for diagnosis\n.execute(&mut *transaction)\n.await\n.map_err(|e| {\n    anyhow::anyhow!(\n        \"Failed to persist migration evidence for intent {} decision {index}: {e:#}\",\n        record.intent_id\n    )\n})?;","handlingStrategy":"validation","validationCode":"// Pre-check before migrating a record's decisions\nif let Some(nonce) = record.nonce {\n    anyhow::ensure!(nonce <= i64::MAX as u64, \"nonce exceeds BIGINT\");\n}\nfor (i, d) in record.decisions.iter().enumerate() {\n    if let Some(h) = d.height_start { anyhow::ensure!(h <= i64::MAX as u64, \"decision {i} height_start exceeds BIGINT\"); }\n    if let Some(h) = d.height_end { anyhow::ensure!(h <= i64::MAX as u64, \"decision {i} height_end exceeds BIGINT\"); }\n}\n// Confirm the table exists with expected shape:\n// SELECT 1 FROM information_schema.columns\n//  WHERE table_name='execution_verification_decision' AND column_name='normalized_value_digest';","typeGuard":null,"tryCatchPattern":"match migration_result {\n    Err(e) if e.to_string().contains(\"duplicate key\") => warn!(\"decision already migrated; continuing idempotently\"),\n    Err(e) => return Err(anyhow!(\"migration aborted: {e:#}\")),\n    Ok(v) => info!(\"migrated {v} records\"),\n}","preventionTips":["Keep schema migrations applied in the same deploy step as the adapter binary upgrade","Pre-validate u64 heights/nonces fit i64 before starting the migration transaction","Ensure intents are inserted before their decision rows in the same transaction","Monitor DB connectivity and pool saturation during bulk migrations"],"tags":["database","sqlx","postgres","migration"],"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"}