{"record":{"id":"57c24cadc761e00b","repo":"nautechsystems/nautilus_trader","slug":"stored-execution-payload-requires-unavailable-key","errorCode":null,"errorMessage":"Stored execution payload requires unavailable key {}","messagePattern":"Stored execution payload requires unavailable key (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/cache/database.rs","lineNumber":7558,"sourceCode":") -> anyhow::Result<()> {\n    let envelopes = sqlx::query_scalar::<_, Vec<u8>>(\n        \"SELECT DISTINCT substring(sealed_transaction FROM 1 FOR 33) \\\n         FROM execution_transaction_hash \\\n         WHERE sealed_transaction IS NOT NULL\",\n    )\n    .fetch_all(&mut **transaction)\n    .await\n    .context(\"failed to inspect execution payload key inventory\")?;\n\n    for header in envelopes {\n        anyhow::ensure!(\n            header.len() == 33,\n            \"Stored execution payload has a truncated envelope header\"\n        );\n        let mut envelope = header;\n        envelope.extend_from_slice(&[0; 12 + 16]);\n        let key_id = envelope_key_id(&envelope)?;\n        anyhow::ensure!(\n            keys.contains_key(&key_id),\n            \"Stored execution payload requires unavailable key {}\",\n            alloy::hex::encode(key_id)\n        );\n    }\n    Ok(())\n}\n\nasync fn load_execution_intent(\n    transaction: &mut Transaction<'_, Postgres>,\n    intent_id: i64,\n) -> anyhow::Result<ExecutionIntentRow> {\n    sqlx::query_as::<_, ExecutionIntentRow>(\n        \"\n        SELECT\n            id, schema_version, chain_id, wallet_address, nonce, purpose, status,\n            client_order_id, trader_id, strategy_id, account_id, instrument_id,\n            pool_address, transaction_to, transaction_input, transaction_value,","sourceCodeStart":7540,"sourceCodeEnd":7576,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/cache/database.rs#L7540-L7576","documentation":"After deriving the key ID from each stored envelope header, the code requires that key to be present in the configured set of available payload keys. A stored payload encrypted with a key the operator has not provisioned cannot be decrypted, so the validation refuses to continue and names the missing key ID.","triggerScenarios":"Validating stored execution payloads when at least one envelope's key ID is absent from the provided key map — e.g. after key rotation removed an old key still referenced by stored data.","commonSituations":"Retiring/rotating keys without retaining old keys needed to read historical payloads; provisioning a new node with only the current key while the DB holds older envelopes; divergent key sets between replicas.","solutions":["Provision the missing key (hex key ID shown in the message) into the configured key set","Re-encrypt or purge payloads sealed with retired keys as part of the rotation procedure","Keep old keys available (archived) until all payloads they sealed are expired or re-sealed"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let required: Vec<[u8;32]> = derive_required_key_ids(&stored_envelopes)?;\nlet missing: Vec<_> = required.iter().filter(|k| !keys.contains_key(k)).collect();\nif !missing.is_empty() { provision_keys(missing)?; }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Retain retired keys (archived) until all payloads they sealed expire","Provision the complete key set, not just the current active key, on new nodes","Keep key material synchronized across replicas sharing the database"],"tags":["database","rust","encryption","missing-key"],"backgroundTag":"missing-credentials","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"}