rustfs/rustfs · error · OnDemandMigrationConfigError

source credentials field {0} must not be empty

Error message

source credentials field {0} must not be empty

What it means

OnDemandMigrationConfigError::EmptyCredential (rustfs/src/on_demand_migration/config.rs:470) is raised by SourceConfig::validate when a `source.credentials` block is present for the on-demand migration source but one of its string fields is empty. The carried `&'static str` names the offending field: `access_key`, `secret_key`, or `session_token`. The library rejects empty credentials at the admin boundary so the migration never starts with a source it cannot authenticate to.

Source

Thrown at rustfs/src/on_demand_migration/config.rs:470

#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
pub enum OnDemandMigrationConfigError {
    #[error("on-demand migration config version {0} is not supported; expected {ON_DEMAND_MIGRATION_CONFIG_VERSION}")]
    UnsupportedVersion(u32),
    #[error("on-demand migration config is not valid JSON: {0}")]
    Malformed(String),
    #[error("source endpoint is required for provider {0}")]
    MissingEndpoint(Provider),
    /// Carries only the reason: the endpoint string is operator input that
    /// may embed credentials, so it is never echoed into an error.
    #[error("source endpoint is invalid: {0}")]
    InvalidEndpoint(&'static str),
    #[error("source region must not be empty")]
    EmptyRegion,
    #[error("source region \"auto\" is not supported for provider {0}")]
    AutoRegionUnsupported(Provider),
    #[error("source bucket is invalid: {0}")]
    InvalidBucket(&'static str),
    #[error("source credentials field {0} must not be empty")]
    EmptyCredential(&'static str),
    #[error("source.{0} is required for provider {1}")]
    MissingProviderBlock(&'static str, Provider),
    #[error("source.{0} is not valid for provider {1}")]
    UnexpectedProviderBlock(&'static str, Provider),
    /// Carries only the reason: the block holds account keys, SAS tokens and
    /// service-account JSON, so no value of it is ever echoed.
    #[error("source.{0} is invalid: {1}")]
    InvalidProviderBlock(&'static str, &'static str),
    #[error("source tls.ca_cert_pem is not a PEM certificate")]
    InvalidCaCert,
    #[error("filter.{0} must be null or a non-empty string")]
    EmptyFilterPrefix(&'static str),
    #[error("policy.{field} = {value} is outside {min}..={max}")]
    OutOfRange {
        field: &'static str,
        value: u64,
        min: u64,

View on GitHub (pinned to 5dca076efe)

Solutions

  1. Populate the field named in the message (access_key, secret_key, or session_token) with the real value, or remove the whole credentials block if the source is public/anonymous.
  2. Check that the environment variable or secret reference backing the field is actually set where the admin config is generated.
  3. Re-submit the corrected config via the admin API so validate() runs again.

Example fix

// before
"credentials": {"access_key": "", "secret_key": "s3cr3t"}
// after
"credentials": {"access_key": "AKIA...", "secret_key": "s3cr3t"}
Defensive patterns

Strategy: validation

Validate before calling

fn creds_ok(c: Option<&SourceCredentials>) -> bool {
    match c {
        None => true,
        Some(c) => !c.access_key.is_empty()
            && !c.secret_key.is_empty()
            && c.session_token.as_deref().map_or(true, |t| !t.is_empty()),
    }
}
assert!(creds_ok(config.source.credentials.as_ref()), "empty credential field");

Type guard

fn non_empty(s: &Option<String>) -> bool { s.as_deref().map_or(true, |v| !v.is_empty()) }

Prevention

When it happens

Trigger: Setting `source.credentials.access_key` or `source.credentials.secret_key` to "" in the migration config JSON (config.rs:616-620), or setting `source.credentials.session_token` to Some("") (config.rs:622-623), then saving/validating the on-demand migration config.

Common situations: Template or UI placeholders left unfilled; an env var like MIGRATION_ACCESS_KEY resolving to empty and being written verbatim into the JSON; a redacted config (xxx in a secrets-management pipeline) copied back and re-submitted.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of rustfs/rustfs@5dca076efe (2026-09-06). Data as JSON: /api/errors/b07eb34009336970. Report an issue: GitHub.