denoland/deno · error

no private key found in OTEL_EXPORTER_OTLP_CLIENT_KEY file

Error message

no private key found in OTEL_EXPORTER_OTLP_CLIENT_KEY file

What it means

For OTLP mTLS, Deno reads a private key from OTEL_EXPORTER_OTLP_CLIENT_KEY and certificates from OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE (both must be set). load_private_keys must yield at least one key from the key file; a PEM with no private key blocks raises this error.

Source

Thrown at ext/telemetry/lib.rs:841

        }
      } else {
        let ca_certs = match std::env::var("OTEL_EXPORTER_OTLP_CERTIFICATE") {
          Ok(path) => vec![sys.fs_read(path)?.into_owned()],
          _ => vec![],
        };

        let keys = match (
          std::env::var("OTEL_EXPORTER_OTLP_CLIENT_KEY"),
          std::env::var("OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE"),
        ) {
          (Ok(key_path), Ok(cert_path)) => {
            let key = sys.fs_read(key_path)?;
            let cert = sys.fs_read(cert_path)?;

            let certs = load_certs(&mut std::io::Cursor::new(cert))?;
            let key =
              load_private_keys(&key)?.into_iter().next().ok_or_else(|| {
                deno_core::anyhow::anyhow!(
                  "no private key found in OTEL_EXPORTER_OTLP_CLIENT_KEY file"
                )
              })?;

            TlsKeys::Static(TlsKey(certs, key))
          }
          _ => TlsKeys::Null,
        };

        let tls_config =
          create_client_config(deno_tls::TlsClientConfigOptions {
            root_cert_store: None,
            ca_certs,
            unsafely_ignore_certificate_errors: None,
            unsafely_disable_hostname_verification: false,
            cert_chain_and_key: keys,
            socket_use: SocketUse::Http,
          })?;

View on GitHub (pinned to 89f33cbef2)

Solutions

  1. Verify the file actually holds a private key: `openssl pkey -in client.key -noout && echo OK`
  2. Point OTEL_EXPORTER_OTLP_CLIENT_KEY at the private-key PEM and OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE at the certificate-chain PEM
  3. Convert encrypted/PKCS#12 material to an unencrypted PEM key: `openssl pkcs12 -nodes -nocerts -in bundle.pfx -out client.key`

Example fix

# before — CLIENT_KEY points at the certificate
export OTEL_EXPORTER_OTLP_CLIENT_KEY=./certs/client.pem
export OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE=./certs/client.pem

# after — key file contains the private key
export OTEL_EXPORTER_OTLP_CLIENT_KEY=./certs/client.key.pem
export OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE=./certs/client.pem
Defensive patterns

Strategy: validation

Validate before calling

key_file="${OTEL_EXPORTER_OTLP_CLIENT_KEY:?}"
if ! grep -q "PRIVATE KEY" "$key_file"; then
  echo "$key_file has no PRIVATE KEY PEM block"; exit 1
fi
openssl pkey -in "$key_file" -noout || exit 1

Prevention

When it happens

Trigger: Both env vars set and the CLIENT_KEY file contains certificates only, is empty, or is in a format the PEM reader cannot parse (e.g. an encrypted key or PKCS#12 bundle).

Common situations: Swapping the two paths; pointing both variables at the same full-chain PEM; using encrypted keys where a plain PKCS#1/PKCS#8 PEM is required.

Related errors


AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16). Data as JSON: /api/errors/b23ec24e04ddf21b. Report an issue: GitHub.