{"record":{"id":"f369d348ec2403e2","repo":"nautechsystems/nautilus_trader","slug":"signed-transaction-envelope-does-not-use-the-datab","errorCode":null,"errorMessage":"Signed transaction envelope does not use the database active key","messagePattern":"Signed transaction envelope does not use the database active key","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"critical","filePath":"crates/adapters/blockchain/src/cache/database.rs","lineNumber":6635,"sourceCode":"                anyhow::anyhow!(\"Failed to start signed transaction persistence: {e}\")\n            })?;\n\n        if let Some(envelope) = sealed_transaction {\n            let state_row = sqlx::query(\n                \"SELECT deployment_id, protocol_version, operation, active_key_id \\\n                 FROM execution_payload_state WHERE component = 'signed_transactions' FOR SHARE\",\n            )\n            .fetch_optional(&mut *transaction)\n            .await\n            .context(\"failed to lock execution payload state for protected persistence\")?\n            .ok_or_else(|| anyhow::anyhow!(\"Execution payload protection is not active\"))?;\n            let state = execution_payload_state_from_row(&state_row)?;\n            anyhow::ensure!(\n                state.protocol_version == EXECUTION_PAYLOAD_PROTOCOL_VERSION\n                    && state.operation == \"ready\",\n                \"Execution payload storage is not ready for protected persistence\"\n            );\n            anyhow::ensure!(\n                envelope_key_id(envelope)?.as_slice() == state.active_key_id.as_slice(),\n                \"Signed transaction envelope does not use the database active key\"\n            );\n        } else {\n            let marker = sqlx::query_scalar::<_, bool>(\n                \"SELECT EXISTS (SELECT 1 FROM execution_schema_version WHERE component = $1)\",\n            )\n            .bind(EXECUTION_PAYLOAD_COMPONENT)\n            .fetch_one(&mut *transaction)\n            .await\n            .context(\"failed to inspect execution payload marker\")?;\n            anyhow::ensure!(\n                !marker,\n                \"Plaintext signed transaction persistence is disabled after payload activation\"\n            );\n        }\n        let current_status = sqlx::query_scalar::<_, String>(\n            \"SELECT status FROM execution_intent WHERE id = $1 FOR UPDATE\",","sourceCodeStart":6617,"sourceCodeEnd":6653,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/cache/database.rs#L6617-L6653","documentation":"This error is raised during protected persistence of a sealed (encrypted) signed transaction. The library locks the execution_payload_state row and requires that the envelope's embedded key id matches the database's active_key_id. If the caller signed the envelope with a rotated, stale, or foreign key, the transaction is rejected so plaintext or wrongly-keyed payloads never reach storage.","triggerScenarios":"Calling add_execution_transaction (or add_execution_transaction_payload with sealed_transaction=Some) while the envelope was encrypted with a key other than execution_payload_state.active_key_id for component 'signed_transactions'. Typically the DB was key-rotated (active_key_id changed) after the caller obtained/cached the old signing key, or the caller is writing to a different database than the one whose key produced the envelope.","commonSituations":"Key rotation performed on the DB between envelope creation and persistence; multiple environments (staging vs prod) sharing a transaction flow; a replica/mismatched connection pointing at a database with a different active key; process restart with a stale in-memory key cache.","solutions":["Refresh the active key id from execution_payload_state (SELECT active_key_id ...) and re-seal the envelope before retrying persistence.","Verify the process is connected to the intended database/environment; compare deployment_id and active_key_id with the target DB.","If a rotation happened mid-flight, run the key-rotation/roll procedure so local signing material matches the new active key.","Retry after re-sealing; do not persist the envelope under the old key."],"exampleFix":"// before\nlet envelope = seal_with(cached_key_id, payload); // stale key\n// after\nlet active = load_active_key_id(pool).await?;\nlet envelope = seal_with(active, payload); // re-seal with DB active key","handlingStrategy":"validation","validationCode":"let state: (Vec<u8>,) = sqlx::query_as(\"SELECT active_key_id FROM execution_payload_state WHERE component='signed_transactions'\").fetch_one(&pool).await?;\nanyhow::ensure!(envelope_key_id(&envelope)?.as_slice() == state.0.as_slice(), \"envelope key id != DB active key; re-seal before persisting\");","typeGuard":"fn uses_active_key(envelope: &[u8], active_key_id: &[u8]) -> bool {\n    envelope_key_id(envelope).map(|k| k.as_slice() == active_key_id).unwrap_or(false)\n}","tryCatchPattern":"match db.add_execution_transaction(intent_id, chain_id, hash, sealed).await {\n    Err(e) if e.to_string().contains(\"does not use the database active key\") => {\n        refresh_active_key(&pool).await?;\n        let resealed = seal(payload, active_key_id).await?;\n        db.add_execution_transaction(intent_id, chain_id, hash, resealed).await?;\n    }\n    result => result?,\n}","preventionTips":["Fetch the active key id from the DB immediately before sealing, never cache across rotations","Subscribe to key-rotation events and invalidate cached signing keys","Tag envelopes with deployment_id and verify it matches the target database","Add a pre-flight check comparing local key material with execution_payload_state on startup"],"tags":["database","encryption","key-mismatch","transactions"],"backgroundTag":"checksum-mismatch","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"}