dani-garcia/vaultwarden · error · opendal::Error

ConfigInvalid

ConfigInvalid

Error message

S3 support is not enabled

What it means

operator_for_path() builds and caches an opendal operator for a storage path. Paths starting with s3:// require the compile-time cargo feature s3 (opendal services-s3 plus AWS credential crates; the default feature set in Cargo.toml is empty, so s3 is opt-in). On a binary built without it, the #[cfg(not(s3))] arm returns opendal ErrorKind::ConfigInvalid 'S3 support is not enabled', which surfaces as an error on the first operation that touches that path (attachment/Send read or write).

Source

Thrown at src/storage.rs:64

    std::path::Path::new(path).file_name()?.to_str().map(str::to_owned)
}

pub(crate) fn is_fs_operator(operator: &opendal::Operator) -> bool {
    operator.info().scheme() == opendal::services::FS_SCHEME
}

pub(crate) fn operator_for_path(path: &str) -> Result<opendal::Operator, crate::Error> {
    // Cache of previously built operators by path
    static OPERATORS_BY_PATH: LazyLock<dashmap::DashMap<String, opendal::Operator>> =
        LazyLock::new(dashmap::DashMap::new);

    if let Some(operator) = OPERATORS_BY_PATH.get(path) {
        return Ok(operator.clone());
    }

    let operator = if path.starts_with("s3://") {
        #[cfg(not(s3))]
        return Err(opendal::Error::new(opendal::ErrorKind::ConfigInvalid, "S3 support is not enabled").into());

        #[cfg(s3)]
        s3::operator_for_path(path)?
    } else {
        let builder = opendal::services::Fs::default().root(path);
        opendal::Operator::new(builder)?
    };

    OPERATORS_BY_PATH.insert(path.to_owned(), operator.clone());

    Ok(operator)
}

#[cfg(s3)]
mod s3 {
    use reqwest::Url;

    use crate::error::Error;

View on GitHub (pinned to 0cefa4cca7)

Solutions

  1. Rebuild with the feature: cargo build --release --no-default-features --features sqlite,s3 (add your DB backend)
  2. Or switch to an image/binary explicitly built with the s3 feature
  3. Or revert to local storage: DATA_FOLDER=/data
  4. Verify the build's feature list before configuring s3:// paths

Example fix

# before
DATA_FOLDER=s3://mybucket/vw-data
# after (option A: local storage)
DATA_FOLDER=/data
# after (option B: build with s3)
cargo build --release --no-default-features --features sqlite,s3
Defensive patterns

Strategy: validation

Validate before calling

# Before pointing storage at S3, confirm this binary has the s3 feature compiled in
BIN="$(command -v vaultwarden)"
if [[ "${DATA_FOLDER:-}" == s3://* ]] && ! strings "$BIN" | grep -q reqsign; then
  echo "FATAL: DATA_FOLDER uses s3:// but this build lacks the 's3' cargo feature" >&2
  exit 1
fi

Type guard

// Compile-time feature probe usable inside the codebase
const S3_FEATURE_ENABLED: bool = cfg!(s3);

Prevention

When it happens

Trigger: Setting DATA_FOLDER (or another storage dir such as ATTACHMENTS_FOLDER) to an s3://bucket/... URL while the running binary was compiled without --features s3; the failure appears lazily on the first storage operation, not at startup.

Common situations: Using a stock binary or distro package and pointing storage at S3; building from source with default features; upgrading to a build that dropped the s3 feature.

Related errors


AI-assisted analysis of dani-garcia/vaultwarden@0cefa4cca7 (2026-08-16). Data as JSON: /api/errors/395d8a0029815dd8. Report an issue: GitHub.