databendlabs/databend · warning
S3 params must remain S3
Error message
S3 params must remain S3
What it means
This unreachable!() lives in a test in storage_params.rs that calls without_credentials() on a StorageParams::S3 and asserts the result is still StorageParams::S3. If the credential-stripping function ever changed the variant type (e.g. converting S3 params to another storage flavor or dropping them), the pattern match fails and the test panics with 'S3 params must remain S3'. It guards the contract that removing credentials never alters the storage variant.
Solutions
- Ensure without_credentials() rebuilds StorageParams::S3 with the same location fields minus credentials
- Keep the S3-specific fields (endpoint_url, region, bucket, root, enable_virtual_host_style) intact when stripping secrets
- Run the storage_params tests (`cargo test -p meta-app-storage -- storage_params`) after changes
Example fix
// before
pub fn without_credentials(&self) -> StorageParams { /* returns wrong variant */ }
// after
pub fn without_credentials(&self) -> StorageParams {
match self {
StorageParams::S3(loc) => StorageParams::S3(loc.without_credentials()),
other => other.clone(),
}
} Defensive patterns
Strategy: validation
Validate before calling
assert!(matches!(params, StorageParams::S3(_)), "without_credentials requires S3 params");
Try / catch
let StorageParams::S3(loc) = params.without_credentials() else {
log::error!("without_credentials changed variant");
return Err(ErrorCode::InternalError("S3 params must remain S3"));
}; Prevention
- Implement without_credentials per-variant, always rebuilding the same variant
- Add tests for every StorageParams variant when adding backends
- Never replace the S3 variant during credential stripping
When it happens
Trigger: Modifying StorageParams::without_credentials or the S3 storage-param types so it no longer returns a StorageParams::S3 variant, then running the storage-params tests.
Common situations: Refactors of StorageParams (adding new storage backends, changing without_credentials to a generic transform); accidental use of a constructor that wraps S3 in another enum variant.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- value for enable_virtual_host_style is invalid
- expect InvalidReply
- The header tree can only contain DataHeader
- not implemented
- bandsave load databend meta data failed
AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11).
Data as JSON: /api/errors/eb215389908602fa.
Report an issue: GitHub.
Appendix: source
Thrown at src/meta/app-storage/src/storage_params.rs:1143
let params = StorageParams::S3(StorageS3Config {
endpoint_url: "http://provider.example:9000".to_string(),
region: "provider-region".to_string(),
bucket: "provider-bucket".to_string(),
root: "provider/root".to_string(),
enable_virtual_host_style: true,
access_key_id: "provider-key".to_string(),
secret_access_key: "provider-secret".to_string(),
security_token: "provider-token".to_string(),
master_key: "provider-master-key".to_string(),
role_arn: "provider-role".to_string(),
external_id: "provider-external-id".to_string(),
disable_credential_loader: true,
allow_credential_chain: Some(true),
..Default::default()
});
let StorageParams::S3(location) = params.without_credentials() else {
unreachable!("S3 params must remain S3");
};
assert_eq!("http://provider.example:9000", location.endpoint_url);
assert_eq!("provider-region", location.region);
assert_eq!("provider-bucket", location.bucket);
assert_eq!("provider/root", location.root);
assert!(location.enable_virtual_host_style);
assert!(location.access_key_id.is_empty());
assert!(location.secret_access_key.is_empty());
assert!(location.security_token.is_empty());
assert!(location.master_key.is_empty());
assert!(location.role_arn.is_empty());
assert!(location.external_id.is_empty());
assert!(!location.disable_credential_loader);
assert_eq!(None, location.allow_credential_chain);
}
}
View on GitHub (pinned to 288d84d76e)