{"record":{"id":"d9d93c1544fa0379","repo":"diem/diem","slug":"key-mismatch-config-0-storage-1","errorCode":null,"errorMessage":"Key mismatch, config: {0}, storage: {1}","messagePattern":"Key mismatch, config: (.+?), storage: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"secure/key-manager/src/lib.rs","lineNumber":75,"sourceCode":"pub enum Action {\n    /// There is no need to perform a rotation (keys are still fresh).\n    NoAction,\n    /// Sufficient time has passed for another key rotation (keys are stale).\n    FullKeyRotation,\n    /// Storage and the blockchain are inconsistent, submit a new rotation transaction.\n    SubmitKeyRotationTransaction,\n    /// The validator config and the validator set are inconsistent, wait for reconfiguration.\n    WaitForReconfiguration,\n    /// Storage and the blockchain are inconsistent, wait for rotation transaction execution.\n    WaitForTransactionExecution,\n}\n\n#[allow(clippy::large_enum_variant)]\n#[derive(Debug, Error, PartialEq, Eq)]\npub enum Error {\n    #[error(\"Key mismatch, config: {0}, info: {1}\")]\n    ConfigInfoKeyMismatch(Ed25519PublicKey, Ed25519PublicKey),\n    #[error(\"Key mismatch, config: {0}, storage: {1}\")]\n    ConfigStorageKeyMismatch(Ed25519PublicKey, Ed25519PublicKey),\n    #[error(\"Data does not exist: {0}\")]\n    DataDoesNotExist(String),\n    #[error(\n        \"The diem_timestamp value on-chain isn't increasing. Last value: {0}, Current value: {1}\"\n    )]\n    LivenessError(u64, u64),\n    #[error(\"Unable to retrieve the account address: {0}, storage error: {1}\")]\n    MissingAccountAddress(String, String),\n    #[error(\"Storage error: {0}\")]\n    StorageError(String),\n    #[error(\"ValidatorInfo not found in ValidatorConfig: {0}\")]\n    ValidatorInfoNotFound(AccountAddress),\n    #[error(\"Unknown error: {0}\")]\n    UnknownError(String),\n}\n\nimpl From<anyhow::Error> for Error {","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/diem/diem/blob/fc4714a8ea273b6efe8b13dbce72ea60aad9a16c/secure/key-manager/src/lib.rs#L57-L93","documentation":"Raised by the diem key-manager when the Ed25519 public key in its config does not match the key stored in the key manager's local storage backend. The manager refuses to act because its local secure storage holds a different key than the one configured. Payloads are the config key and the storage key.","triggerScenarios":"During key manager startup/execution, the configured key (e.g. validator_key in config) is compared against the key loaded from SecureStorage and the two Ed25519PublicKey values differ.","commonSituations":"Pointing the key manager at a storage database from a different validator or an old deployment, restoring config from a template while keeping an old storage backend, or a partially completed key rotation that updated storage but not config.","solutions":["Fix the key manager config to reference the key actually stored in the storage backend","Or update the storage backend entry (validator key) to the configured key if the config is authoritative","Ensure the key manager is connected to the intended storage namespace/directory for this validator","Re-run key rotation end-to-end if a previous rotation was interrupted"],"exampleFix":"// before (config points at new key, storage still holds old key)\nvalidator_key: \"new-key\"\n// after: make config match storage, or rotate storage to new key via the key manager\nvalidator_key: \"<key present in secure storage>\"","handlingStrategy":"validation","validationCode":"let config_key = load_config()?.validator_key.public_key();\nlet storage_key: Ed25519PublicKey = storage.get(&ValidatorKeyPath)?;\nassert_eq!(config_key, storage_key, \"config key must match key in secure storage\");","typeGuard":"fn config_matches_storage(config: &Ed25519PublicKey, stored: &Ed25519PublicKey) -> bool { config == stored }","tryCatchPattern":"match result {\n    Err(Error::ConfigStorageKeyMismatch(cfg, stored)) => eprintln!(\"fix config or storage: config={}, storage={}\", cfg, stored),\n    Err(e) => return Err(e.into()),\n    Ok(v) => Ok(v),\n}","preventionTips":["Always pair config edits with the matching storage entry updates","Point every validator's key manager at its own dedicated storage namespace","Snapshot storage and config together so restores stay consistent","Verify storage contents after interrupted key rotations before restarting"],"tags":["rust","key-management","storage","config-mismatch"],"backgroundTag":"public-key-mismatch","analyzedSha":"fc4714a8ea273b6efe8b13dbce72ea60aad9a16c","analyzedAt":"2026-09-04T21:07:05.890Z","contentChangedAt":"2026-09-04T21:07:05.890Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}