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
- 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.
- Check that the environment variable or secret reference backing the field is actually set where the admin config is generated.
- 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
- Resolve secret env vars and fail fast on empty strings before building the config JSON.
- Never round-trip redacted configs back into the admin API.
- Omit the credentials block entirely for anonymous/public sources instead of writing empty strings.
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
- Connect heartbeat schedule is invalid
- Expiration cannot specify both Days and Date
- source.{0} is required for provider {1}
- source.{0} is not valid for provider {1}
- source.{0} is invalid: {1}
AI-assisted analysis of rustfs/rustfs@5dca076efe (2026-09-06).
Data as JSON: /api/errors/b07eb34009336970.
Report an issue: GitHub.