{"record":{"id":"395d8a0029815dd8","repo":"dani-garcia/vaultwarden","slug":"configinvalid","errorCode":"ConfigInvalid","errorMessage":"S3 support is not enabled","messagePattern":"S3 support is not enabled","errorType":"http","errorClass":"opendal::Error","httpStatus":400,"severity":"error","filePath":"src/storage.rs","lineNumber":64,"sourceCode":"    std::path::Path::new(path).file_name()?.to_str().map(str::to_owned)\n}\n\npub(crate) fn is_fs_operator(operator: &opendal::Operator) -> bool {\n    operator.info().scheme() == opendal::services::FS_SCHEME\n}\n\npub(crate) fn operator_for_path(path: &str) -> Result<opendal::Operator, crate::Error> {\n    // Cache of previously built operators by path\n    static OPERATORS_BY_PATH: LazyLock<dashmap::DashMap<String, opendal::Operator>> =\n        LazyLock::new(dashmap::DashMap::new);\n\n    if let Some(operator) = OPERATORS_BY_PATH.get(path) {\n        return Ok(operator.clone());\n    }\n\n    let operator = if path.starts_with(\"s3://\") {\n        #[cfg(not(s3))]\n        return Err(opendal::Error::new(opendal::ErrorKind::ConfigInvalid, \"S3 support is not enabled\").into());\n\n        #[cfg(s3)]\n        s3::operator_for_path(path)?\n    } else {\n        let builder = opendal::services::Fs::default().root(path);\n        opendal::Operator::new(builder)?\n    };\n\n    OPERATORS_BY_PATH.insert(path.to_owned(), operator.clone());\n\n    Ok(operator)\n}\n\n#[cfg(s3)]\nmod s3 {\n    use reqwest::Url;\n\n    use crate::error::Error;","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/dani-garcia/vaultwarden/blob/0cefa4cca7c9f2a5579dd290f78193b543818c51/src/storage.rs#L46-L82","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Rebuild with the feature: cargo build --release --no-default-features --features sqlite,s3 (add your DB backend)","Or switch to an image/binary explicitly built with the s3 feature","Or revert to local storage: DATA_FOLDER=/data","Verify the build's feature list before configuring s3:// paths"],"exampleFix":"# before\nDATA_FOLDER=s3://mybucket/vw-data\n# after (option A: local storage)\nDATA_FOLDER=/data\n# after (option B: build with s3)\ncargo build --release --no-default-features --features sqlite,s3","handlingStrategy":"validation","validationCode":"# Before pointing storage at S3, confirm this binary has the s3 feature compiled in\nBIN=\"$(command -v vaultwarden)\"\nif [[ \"${DATA_FOLDER:-}\" == s3://* ]] && ! strings \"$BIN\" | grep -q reqsign; then\n  echo \"FATAL: DATA_FOLDER uses s3:// but this build lacks the 's3' cargo feature\" >&2\n  exit 1\nfi","typeGuard":"// Compile-time feature probe usable inside the codebase\nconst S3_FEATURE_ENABLED: bool = cfg!(s3);","tryCatchPattern":null,"preventionTips":["Decide the storage backend before deployment and build the matching feature set","Keep DATA_FOLDER on a local volume unless the build explicitly includes s3","Record the cargo features used in deployment notes or image labels","Test one attachment upload after switching storage backends"],"tags":["rust","storage","s3","feature-flags","configuration"],"backgroundTag":null,"analyzedSha":"0cefa4cca7c9f2a5579dd290f78193b543818c51","analyzedAt":"2026-08-16T07:44:56.102Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}