BloopAI/vibe-kanban · critical

Failed to install rustls crypto provider

Error message

Failed to install rustls crypto provider

What it means

rustls requires exactly one process-wide crypto provider; install_default() returns Err if another provider (ring, aws-lc-rs, or a custom one) was already installed. The code expects it to succeed, so calling main() when a provider was already installed panics with "Failed to install rustls crypto provider".

Source

Thrown at crates/remote/src/main.rs:11

use remote::{
    BillingService, SentrySource, Server, config::RemoteServerConfig, init_tracing,
    sentry_init_once,
};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Install rustls crypto provider before any TLS operations
    rustls::crypto::aws_lc_rs::default_provider()
        .install_default()
        .expect("Failed to install rustls crypto provider");

    sentry_init_once(SentrySource::Remote);
    init_tracing();

    let config = RemoteServerConfig::from_env()?;

    #[cfg(feature = "vk-billing")]
    let billing = {
        use std::sync::Arc;

        use billing::{BillingConfig, BillingProvider, StripeBillingProvider};
        use remote::db;

        match BillingConfig::from_env()? {
            Some(billing_config) => {
                let pool = db::create_pool(&config.database_url).await?;
                let provider: Arc<dyn BillingProvider> = Arc::new(StripeBillingProvider::new(
                    pool,

View on GitHub (pinned to 4deb7eca8f)

Solutions

  1. Use try_install_default() and ignore the AlreadyInstalled error instead of expect
  2. Ensure only one TLS stack is enabled across Cargo features (prefer rustls with aws-lc-rs everywhere)
  3. If this runs in tests, install the provider once with std::sync::Once in a shared helper

Example fix

// before
rustls::crypto::aws_lc_rs::default_provider().install_default().expect("Failed to install rustls crypto provider");
// after
let _ = rustls::crypto::aws_lc_rs::default_provider().try_install_default();
Defensive patterns

Strategy: try-catch

Validate before calling

// is a CryptoProvider already installed?
let provider_installed = std::env::var("RUSTLS_CRYPTO_PROVIDER").is_ok(); // heuristic; runtime state is private
// safer: use try_install_default and inspect the Result

Try / catch

match rustls::crypto::aws_lc_rs::default_provider().install_default() {
    Ok(()) => {},
    Err(_) => { /* already installed — continue */ }
}

Prevention

When it happens

Trigger: `main` in crates/remote runs and `install_default()` fails because a different rustls CryptoProvider was already installed earlier in the process (e.g. by a dependency using ring::default_provider or a prior install_default call).

Common situations: Mixing dependencies that each install a rustls provider (ring vs aws-lc-rs); calling main's logic twice in tests; a library upgrade that now installs its own default provider at startup.

Related errors


AI-assisted analysis of BloopAI/vibe-kanban@4deb7eca8f (2026-08-29). Data as JSON: /api/errors/303c88c58efd1693. Report an issue: GitHub.