tauri-apps/tauri · error

failed to parse TAURI_DEV_ROOT_CERTIFICATE

Error message

failed to parse TAURI_DEV_ROOT_CERTIFICATE

What it means

If TAURI_DEV_ROOT_CERTIFICATE is set when the tauri crate is COMPILED (option_env!), its bytes are embedded and added as a trusted root certificate for the dev-server HTTPS client via reqwest::Certificate::from_pem. The expect panics at app startup in dev when the embedded value is not a valid PEM certificate.

Source

Thrown at crates/tauri/src/protocol/tauri.rs:59

    let mut client_builder = reqwest::ClientBuilder::new();
    if use_https {
      #[cfg(feature = "rustls-tls")]
      if rustls::crypto::CryptoProvider::get_default().is_none() {
        let _ = rustls::crypto::ring::default_provider().install_default();
      }

      // we can't load env vars at runtime, gotta embed them in the lib
      #[allow(unused_variables)]
      if let Some(cert_pem) = option_env!("TAURI_DEV_ROOT_CERTIFICATE") {
        #[cfg(any(
          feature = "native-tls",
          feature = "native-tls-vendored",
          feature = "rustls-tls"
        ))]
        {
          log::info!("adding dev server root certificate");
          let certificate = reqwest::Certificate::from_pem(cert_pem.as_bytes())
            .expect("failed to parse TAURI_DEV_ROOT_CERTIFICATE");
          client_builder = client_builder.tls_certs_merge([certificate]);
        }

        #[cfg(not(any(
          feature = "native-tls",
          feature = "native-tls-vendored",
          feature = "rustls-tls"
        )))]
        {
          log::warn!(
            "the dev root-certificate-path option was provided, but you must enable one of the following Tauri features in Cargo.toml: native-tls, native-tls-vendored, rustls-tls"
          );
        }
      } else {
        log::warn!(
          "loading HTTPS URL; you might need to provide a certificate via the `dev --root-certificate-path` option. You must enable one of the following Tauri features in Cargo.toml: native-tls, native-tls-vendored, rustls-tls"
        );
      }

View on GitHub (pinned to 52e4b6e71d)

Solutions

  1. Convert DER to PEM: openssl x509 -inform der -in ca.cer -out ca.pem and use that content.
  2. Ensure the value is a valid PEM CERTIFICATE block (correct base64 and BEGIN/END lines).
  3. After changing the value, fully rebuild so the new env var is embedded.
  4. Validate quickly: openssl x509 -in ca.pem -noout must succeed.
  5. Unset the variable if a custom dev root CA is no longer needed.

Example fix

# before
export TAURI_DEV_ROOT_CERTIFICATE="$(cat ca.cer)"   # DER bytes -> panic

# after
openssl x509 -inform der -in ca.cer -out ca.pem
export TAURI_DEV_ROOT_CERTIFICATE="$(cat ca.pem)"   # valid PEM
cargo clean && cargo tauri dev
Defensive patterns

Strategy: validation

Validate before calling

# fail fast if the PEM is invalid, before compiling tauri
openssl x509 -in "$TAURI_DEV_ROOT_CERTIFICATE" -noout >/dev/null \
  || { echo 'TAURI_DEV_ROOT_CERTIFICATE is not a valid PEM certificate'; exit 1; }

Prevention

When it happens

Trigger: TAURI_DEV_ROOT_CERTIFICATE containing DER/binary cert data, malformed base64, missing -----BEGIN CERTIFICATE----- / -----END CERTIFICATE----- markers, or a bundle with PEM blocks reqwest cannot use. The panic happens at runtime even though the env var was captured at compile time.

Common situations: Exporting a CA as .cer/.der; concatenating extra PEM sections (keys, CRLs); truncated file; stale embedded value after changing the env var without a rebuild (rust option_env! is compile-time).

Understand the failure class

Related errors


AI-assisted analysis of tauri-apps/tauri@52e4b6e71d (2026-08-20). Data as JSON: /api/errors/742571b37098cea9. Report an issue: GitHub.