risingwavelabs/risingwave · error · SecretError

unspecified secret ref type: {0}

Error message

unspecified secret ref type: {0}

What it means

SecretError::UnspecifiedRefType is raised when a secret reference carries a SecretId but the reference's type field is not set (unspecified), so the secret resolver cannot tell how to interpret or look up the reference. The SecretId is included in the message for diagnosis.

Source

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

use thiserror::Error;
use thiserror_ext::Construct;

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. Set the reference type explicitly when building the secret ref in the client/SQL layer.
  2. Upgrade/fix the component that produced the proto so it fills the ref type field.
  3. Inspect the stored proto message for the given SecretId and re-create it with a valid type.

Example fix

// before
let ref = SecretRef { id: some_id, ..Default::default() }; // type unspecified
resolve(ref)?;

// after
let ref = SecretRef { id: some_id, ref_type: RefType::Compat, ..Default::default() };
resolve(ref)?;
Defensive patterns

Strategy: validation

Validate before calling

// Validate a secret ref has a concrete type before resolving:
fn ref_type_is_set(r: &SecretRef) -> bool {
    !matches!(r.ref_type, None | Some(RefType::Unspecified))
}

Type guard

fn valid_secret_ref(r: &SecretRef) -> Option<&SecretRef> {
    match r.ref_type {
        Some(RefType::Unspecified) | None => None,
        Some(_) => Some(r),
    }
}

Try / catch

match resolver.resolve(&secret_ref).await {
    Ok(secret) => secret,
    Err(SecretError::UnspecifiedRefType(id)) => {
        // producer bug: ref built without setting its type — reject and re-create
        return Err(anyhow!("secret ref {id} has no type; rebuild the reference"));
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Constructing or deserializing a secret ref (e.g. from protobuf) where the type/ref-kind field is left at its default/unspecified value and then attempting to resolve it, producing SecretError::UnspecifiedRefType(id).

Common situations: A protobuf message for a secret reference was built without setting the ref type oneof/enum (default zero value); older clients or proto schema drift omitting a newly required field; hand-written serialization of a secret ref skipping the type.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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