stalwartlabs/stalwart · critical
failed to install aws-lc-rs as the default rustls crypto pro
Error message
failed to install aws-lc-rs as the default rustls crypto provider
What it means
Rustls requires exactly one process-wide default crypto provider. This panic fires when `aws_lc_rs::default_provider().install_default()` returns Err, which happens only if a default provider was already installed (or another provider was installed first, e.g. by a dependency using ring). The process cannot start because TLS cannot be configured as intended.
Source
Thrown at crates/main/src/main.rs:38
use trc::Collector;
use utils::wait_for_shutdown;
#[cfg(feature = "dev_mode")]
pub mod test_data;
#[cfg(not(any(target_env = "msvc", target_os = "freebsd")))]
use tikv_jemallocator::Jemalloc;
#[cfg(not(any(target_env = "msvc", target_os = "freebsd")))]
#[global_allocator]
static GLOBAL: Jemalloc = Jemalloc;
#[tokio::main]
async fn main() -> std::io::Result<()> {
// Install AWS-LC-RS as the default Rustls crypto provider
rustls::crypto::aws_lc_rs::default_provider()
.install_default()
.expect("failed to install aws-lc-rs as the default rustls crypto provider");
// Build the shared outbound TLS configurations
utils::http::init_shared_tls_configs();
// Load config and apply macros
let mut init = Box::pin(BootManager::init()).await;
// Migrate database
if let Err(err) = migration::try_migrate(&init.inner.build_server()).await {
trc::event!(
Server(trc::ServerEvent::StartupError),
Details = "Failed to migrate database, aborting startup.",
Reason = err,
);
return Ok(());
}
// Init servicesView on GitHub (pinned to e962003857)
Solutions
- Ensure no dependency installs a rustls provider before main runs; check Cargo features for duplicate crypto provider crates (ring + aws-lc-rs)
- If a provider may already be installed, replace install_default().expect() with try_install() or check the Result instead of panicking
- Explicitly pass the provider to ClientConfig/ServerConfig builders instead of relying on the process default
- Update dependencies so only one TLS crypto provider is active
Example fix
// before
rustls::crypto::aws_lc_rs::default_provider()
.install_default()
.expect("failed to install aws-lc-rs as the default rustls crypto provider");
// after
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); Defensive patterns
Strategy: fallback
Try / catch
// install_default returns Result; don't panic if a provider exists:
if rustls::crypto::CryptoProvider::get_default().is_none() {
rustls::crypto::aws_lc_rs::default_provider()
.install_default()
.expect("failed to install default crypto provider");
} Prevention
- Audit Cargo features for multiple rustls crypto provider crates
- Do not install a crypto provider in library code; leave it to the binary's main
- Prefer passing providers explicitly to config builders over process-global defaults
When it happens
Trigger: Calling main after some other code path (a dependency, an earlier init, or duplicate installation) has already installed a rustls CryptoProvider via `install_default()`, or having two provider installations in the binary.
Common situations: A dependency (e.g. a library that installs the ring provider) is pulled in and initializes before main; the binary is built with both ring and aws-lc-rs features and some crate initializes ring first; duplicate install calls in embedded/test setups.
Related errors
- Failed to load the platform certificate verifier
- Failed to build the TLS client configuration
- Node id {node_id} exceeds {MAX_NODE_ID}, panicking to avoid
- Invalid system time, panicking to avoid data corruption
- unwrap_tls called on non-TLS acceptor
AI-assisted analysis of stalwartlabs/stalwart@e962003857 (2026-09-06).
Data as JSON: /api/errors/b1da277453923300.
Report an issue: GitHub.