risingwavelabs/risingwave · error

secret_store_private_key is not configured

Error message

secret_store_private_key is not configured

What it means

Secrets in RisingWave are encrypted at rest with a cluster-wide private key (secret_store_private_key). get_encrypted_payload reads this key from meta node options before encrypting a secret value; if the option was never configured, encryption cannot proceed and the create/alter secret operation fails.

Source

Thrown at src/meta/src/rpc/ddl_controller.rs:848

    ) -> MetaResult<NotificationVersion> {
        let version = self
            .metadata_manager
            .catalog_controller
            .alter_database_resource_group(database_id, resource_group)
            .await?;

        Ok(version)
    }

    // The 'secret' part of the request we receive from the frontend is in plaintext;
    // here, we need to encrypt it before storing it in the catalog.
    fn get_encrypted_payload(&self, secret: &Secret) -> MetaResult<Vec<u8>> {
        let secret_store_private_key = self
            .env
            .opts
            .secret_store_private_key
            .clone()
            .ok_or_else(|| anyhow!("secret_store_private_key is not configured"))?;

        let encrypted_payload = SecretEncryption::encrypt(
            secret_store_private_key.as_slice(),
            secret.get_value().as_slice(),
        )
        .context(format!("failed to encrypt secret {}", secret.name))?;
        Ok(encrypted_payload
            .serialize()
            .context(format!("failed to serialize secret {}", secret.name))?)
    }

    async fn create_secret(&self, mut secret: Secret) -> MetaResult<NotificationVersion> {
        // The 'secret' part of the request we receive from the frontend is in plaintext;
        // here, we need to encrypt it before storing it in the catalog.
        let secret_plain_payload = secret.value.clone();
        let encrypted_payload = self.get_encrypted_payload(&secret)?;
        secret.value = encrypted_payload;

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Add secret_store_private_key to the meta node configuration and restart the meta service.
  2. Verify the key is present via risingwave.toml / meta opts before enabling secret workflows.
  3. If the key was lost, restore it from backups — an existing encrypted store needs the same key to remain readable.

Example fix

// before (risingwave.toml)
[meta]
# secret_store_private_key missing
// after
[meta]
secret_store_private_key = "<base64-encoded-key>"
Defensive patterns

Strategy: validation

Validate before calling

// before CREATE SECRET, check config
let key = std::env::var("RW_SECRET_STORE_PRIVATE_KEY")
    .or(meta_opts.secret_store_private_key.clone());
if key.is_none() { return Err("set secret_store_private_key in meta config first".into()); }

Try / catch

match create_secret(...).await {
    Err(e) if e.to_string().contains("secret_store_private_key is not configured") => configure_and_retry(),
    other => other?,
}

Prevention

When it happens

Trigger: Calling CREATE SECRET or ALTER SECRET when the meta node was started without secret_store_private_key in its configuration/opts.

Common situations: Deployments that never enabled the secret store feature attempting to use secrets; a config file copied between environments dropping the key; upgrading a cluster where the key was added to docs but not the actual meta opts.

Understand the failure class

Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.

Related errors


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