{"record":{"id":"a424806e7392a9e6","repo":"nautechsystems/nautilus_trader","slug":"failed-to-lock-canonical-nonce-ledger-e","errorCode":null,"errorMessage":"Failed to lock canonical nonce ledger: {e}","messagePattern":"Failed to lock canonical nonce ledger: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/cache/database.rs","lineNumber":5926,"sourceCode":"        let mut transaction = self\n            .pool\n            .begin()\n            .await\n            .map_err(|e| anyhow::anyhow!(\"Failed to start verified nonce assignment: {e}\"))?;\n        let (manifest_version, manifest_digest, next_nonce, revision) =\n            sqlx::query_as::<_, (String, String, i64, i64)>(\n                \"\n                SELECT manifest_version, manifest_digest, next_canonical_nonce, revision\n                FROM execution_verification_nonce\n                WHERE chain_id = $1 AND wallet_address = $2\n                FOR UPDATE\n                \",\n            )\n            .bind(chain_id)\n            .bind(assignment.wallet_address)\n            .fetch_optional(&mut *transaction)\n            .await\n            .map_err(|e| anyhow::anyhow!(\"Failed to lock canonical nonce ledger: {e}\"))?\n            .ok_or_else(|| anyhow::anyhow!(\"Canonical nonce ledger is not initialized\"))?;\n        anyhow::ensure!(\n            manifest_version == assignment.manifest_version\n                && manifest_digest == assignment.manifest_digest,\n            \"Verified nonce assignment manifest identity changed\"\n        );\n        anyhow::ensure!(\n            next_nonce == nonce,\n            \"Execution nonce {} does not match canonical nonce {next_nonce}\",\n            assignment.nonce\n        );\n\n        let (intent_chain_id, intent_wallet, intent_nonce, intent_status, intent_active) =\n            sqlx::query_as::<_, (i32, String, Option<i64>, String, bool)>(\n                \"\n            SELECT chain_id, wallet_address, nonce, status, active\n            FROM execution_intent\n            WHERE id = $1","sourceCodeStart":5908,"sourceCodeEnd":5944,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/cache/database.rs#L5908-L5944","documentation":"Inside the begun transaction, this code runs the locking SELECT against `execution_verification_nonce` for (chain_id, wallet_address); the sqlx query itself failed. The row lock is what serializes nonce assignment, so any query failure aborts the whole assignment transaction. The `{e}` carries the underlying sqlx/database error.","triggerScenarios":"The locking SELECT against `execution_verification_nonce` returns a database error: connection dropped mid-transaction, statement timeout, serialization/deadlock failure, permission denied on the table, or the table/schema missing.","commonSituations":"Migrations not applied (table absent) in a fresh environment; role lacking SELECT privilege; deadlock with another writer assigning nonces concurrently; statement_timeout set too low; DB failover severing the connection.","solutions":["Inspect the wrapped `{e}` error to identify whether it is a connectivity, timeout, permission, or missing-table error.","Run pending migrations so `execution_verification_nonce` exists.","Grant the database role SELECT/UPDATE on the nonce table.","If deadlock/serialization, retry the operation; the transaction is aborted so a fresh attempt is safe.","Check for long-running transactions holding the row lock and reduce lock contention."],"exampleFix":"// before\n retry without backoff on lock failure\n// after\n match err { e if is_deadlock(&e) => retry_with_backoff(op, 3), e => return Err(e) }","handlingStrategy":"retry","validationCode":"let table_ok = sqlx::query(\"SELECT 1 FROM information_schema.tables WHERE table_name = 'execution_verification_nonce'\").fetch_optional(&pool).await?.is_some();\nif !table_ok { return Err(anyhow!(\"nonce ledger table missing; run migrations\")); }","typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if is_transient_db_error(&e) => retry_with_backoff(op, 3), // deadlock, timeout, connection reset\n    Err(e) => return Err(e.context(\"nonce ledger lock failed permanently\")),\n    Ok(v) => Ok(v),\n}","preventionTips":["Apply all migrations as part of deployment before serving traffic.","Grant the app role the needed privileges on execution_verification_nonce.","Keep transactions short to avoid deadlocks and statement timeouts.","Set statement_timeout above your worst-case query time, not below.","Retry deadlock/serialization failures with jittered backoff — they are expected under contention."],"tags":["database","postgres","row-lock","transaction"],"backgroundTag":"database-query-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"}