grafana/k6 · error

failed to append root certificate to the pool

Error message

failed to append root certificate to the pool

What it means

Thrown while building TLS config for the OpenTelemetry output when the PEM file at K6_OTEL_TLS_CERTIFICATE exists and was read successfully, but x509.CertPool.AppendCertsFromPEM returned false, meaning the bytes contained no parseable PEM certificate block. This guards against corrupt or misformatted CA bundles before the exporter connects.

Source

Thrown at internal/output/opentelemetry/tls.go:36

	tlsConfig := &tls.Config{
		MinVersion: tls.VersionTLS13,
	}

	if insecureSkipVerify.Valid {
		tlsConfig.InsecureSkipVerify = insecureSkipVerify.Bool
		set = true
	}

	// Load the root certificate
	if certPath.Valid {
		b, err := os.ReadFile(certPath.String) //nolint:forbidigo
		if err != nil {
			return nil, fmt.Errorf("failed to read root certificate from %q: %w", certPath.String, err)
		}

		cp := x509.NewCertPool()
		if ok := cp.AppendCertsFromPEM(b); !ok {
			return nil, errors.New("failed to append root certificate to the pool")
		}

		tlsConfig.RootCAs = cp
		set = true
	}

	// Load the client certificate
	if clientCertPath.Valid {
		cert, err := tls.LoadX509KeyPair(clientCertPath.String, clientKeyPath.String)
		if err != nil {
			return nil, fmt.Errorf("failed to load client certificate: %w", err)
		}

		tlsConfig.Certificates = []tls.Certificate{cert}
		set = true
	}

	if !set {

View on GitHub (pinned to 93accf6570)

Solutions

  1. Verify the file is PEM: it must contain '-----BEGIN CERTIFICATE-----' blocks; openssl x509 -in ca.pem -text -noout should succeed
  2. Convert DER to PEM: openssl x509 -inform der -in ca.der -out ca.pem
  3. Check you passed the CA bundle path, not the client cert/key (use K6_OTEL_TLS_CLIENT_CERTIFICATE + K6_OTEL_TLS_CLIENT_KEY for mTLS)
  4. Re-export the certificate from the source of truth to repair truncation or CRLF damage

Example fix

# before
# ca.der is binary DER -> AppendCertsFromPEM fails
export K6_OTEL_TLS_CERTIFICATE=/certs/ca.der

# after
openssl x509 -inform der -in /certs/ca.der -out /certs/ca.pem
export K6_OTEL_TLS_CERTIFICATE=/certs/ca.pem
Defensive patterns

Strategy: validation

Validate before calling

# Fail fast on non-PEM CA bundles before running k6:
CA=${K6_OTEL_TLS_CERTIFICATE:?}
openssl x509 -in "$CA" -noout 2>/dev/null || { echo "$CA is not valid PEM"; exit 1; }

Prevention

When it happens

Trigger: Pointing K6_OTEL_TLS_CERTIFICATE at a DER-encoded (binary) CA file instead of PEM; a certificate file that was truncated, mangled by templating, or contains only a private key/certificate chain header without CERTIFICATE blocks; accidentally passing the client key path in the CA field; line-ending corruption (CRLF injection) from Windows tooling.

Common situations: Ops teams exporting certs from vaults that re-encode formats; copy-paste errors that drop BEGIN/END lines; mixing up K6_OTEL_TLS_CERTIFICATE (root CA) with K6_OTEL_TLS_CLIENT_CERTIFICATE (mutual TLS pair).

Understand the failure class

Related errors


AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15). Data as JSON: /api/errors/76979d8cd93801dc. Report an issue: GitHub.