risingwavelabs/risingwave · error · SecretError

failed to encrypt or decrypt the secret

Error message

failed to encrypt or decrypt the secret

What it means

SecretError::AesError is a fixed-message variant raised when encrypting or decrypting a secret fails. It carries no cause, so the AES cipher operation itself rejected the input (bad key size, invalid ciphertext, padding errors, etc.) and the code collapses it into this opaque error.

Source

Thrown at src/common/secret/src/error.rs:37

use super::SecretId;

pub type SecretResult<T> = Result<T, SecretError>;

#[derive(Error, Debug, Construct)]
pub enum SecretError {
    #[error("secret not found: {0}")]
    ItemNotFound(SecretId),

    #[error("decode utf8 error: {0}")]
    DecodeUtf8Error(#[from] std::string::FromUtf8Error),

    #[error("I/O error: {0}")]
    IoError(#[from] std::io::Error),

    #[error("unspecified secret ref type: {0}")]
    UnspecifiedRefType(SecretId),

    #[error("failed to encrypt or decrypt the secret")]
    AesError,

    #[error("ser/de proto message error: {0}")]
    ProtoError(#[from] bincode::Error),

    #[error(transparent)]
    Internal(#[from] anyhow::Error),
}

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Restore/keep the original encryption key used when the secrets were written.
  2. Re-create the affected secrets so they are encrypted with the current key.
  3. Check for key rotation/migration procedures and re-encrypt stored secrets as part of it.
  4. If blobs are corrupted, delete and re-ingest the secret values.

Example fix

// before
// env key changed after secrets were encrypted with the old key
RW_ENCRYPTION_KEY=newkey risingwave --listen ... // decrypt fails: AesError

// after
RW_ENCRYPTION_KEY=<original-key> risingwave --listen ...
// then re-CREATE SECRETs so they are re-encrypted under the current key
Defensive patterns

Strategy: try-catch

Try / catch

match manager.get(id).await {
    Ok(secret) => secret,
    Err(SecretError::AesError) => {
        // decryption failed: key mismatch or corrupted blob.
        // Non-retryable — re-create the secret under the current key.
        return Err(anyhow!("cannot decrypt secret {id}; re-create it (AesError)"));
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Attempting to decrypt a secret blob with a key that does not match the one used to encrypt it; encrypt/decrypt helpers receiving malformed or truncated ciphertext; AES key material of invalid length being used in the secret encryption path.

Common situations: The cluster encryption key was rotated or changed while old encrypted secrets persisted in meta storage; secrets copied between environments with different encryption keys; corrupted secret blobs after a bad restore/migration.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/28e7354cdbe51b12. Report an issue: GitHub.