diem/diem · error · Error

Key mismatch, config: {0}, storage: {1}

Error message

Key mismatch, config: {0}, storage: {1}

What it means

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.

Source

Thrown at secure/key-manager/src/lib.rs:75

pub enum Action {
    /// There is no need to perform a rotation (keys are still fresh).
    NoAction,
    /// Sufficient time has passed for another key rotation (keys are stale).
    FullKeyRotation,
    /// Storage and the blockchain are inconsistent, submit a new rotation transaction.
    SubmitKeyRotationTransaction,
    /// The validator config and the validator set are inconsistent, wait for reconfiguration.
    WaitForReconfiguration,
    /// Storage and the blockchain are inconsistent, wait for rotation transaction execution.
    WaitForTransactionExecution,
}

#[allow(clippy::large_enum_variant)]
#[derive(Debug, Error, PartialEq, Eq)]
pub enum Error {
    #[error("Key mismatch, config: {0}, info: {1}")]
    ConfigInfoKeyMismatch(Ed25519PublicKey, Ed25519PublicKey),
    #[error("Key mismatch, config: {0}, storage: {1}")]
    ConfigStorageKeyMismatch(Ed25519PublicKey, Ed25519PublicKey),
    #[error("Data does not exist: {0}")]
    DataDoesNotExist(String),
    #[error(
        "The diem_timestamp value on-chain isn't increasing. Last value: {0}, Current value: {1}"
    )]
    LivenessError(u64, u64),
    #[error("Unable to retrieve the account address: {0}, storage error: {1}")]
    MissingAccountAddress(String, String),
    #[error("Storage error: {0}")]
    StorageError(String),
    #[error("ValidatorInfo not found in ValidatorConfig: {0}")]
    ValidatorInfoNotFound(AccountAddress),
    #[error("Unknown error: {0}")]
    UnknownError(String),
}

impl From<anyhow::Error> for Error {

View on GitHub (pinned to fc4714a8ea)

Solutions

  1. Fix the key manager config to reference the key actually stored in the storage backend
  2. Or update the storage backend entry (validator key) to the configured key if the config is authoritative
  3. Ensure the key manager is connected to the intended storage namespace/directory for this validator
  4. Re-run key rotation end-to-end if a previous rotation was interrupted

Example fix

// before (config points at new key, storage still holds old key)
validator_key: "new-key"
// after: make config match storage, or rotate storage to new key via the key manager
validator_key: "<key present in secure storage>"
Defensive patterns

Strategy: validation

Validate before calling

let config_key = load_config()?.validator_key.public_key();
let storage_key: Ed25519PublicKey = storage.get(&ValidatorKeyPath)?;
assert_eq!(config_key, storage_key, "config key must match key in secure storage");

Type guard

fn config_matches_storage(config: &Ed25519PublicKey, stored: &Ed25519PublicKey) -> bool { config == stored }

Try / catch

match result {
    Err(Error::ConfigStorageKeyMismatch(cfg, stored)) => eprintln!("fix config or storage: config={}, storage={}", cfg, stored),
    Err(e) => return Err(e.into()),
    Ok(v) => Ok(v),
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of diem/diem@fc4714a8ea (2026-09-04). Data as JSON: /api/errors/d9d93c1544fa0379. Report an issue: GitHub.