cloudflare/cloudflared · error

Error loading cert pool

Error message

Error loading cert pool

What it means

newHTTPTransport builds the http.Transport used to reach HTTP(S) origins and first loads the origin CA pool with tlsconfig.LoadOriginCA (from cfg.CAPool). If the CA pool cannot be read or parsed, the error is wrapped with this message and the origin transport cannot be constructed, so the service fails to start.

Source

Thrown at ingress/origin_service.go:349

		Service:  newManagementService(management),
	}
}

type NopReadCloser struct{}

// Read always returns EOF to signal end of input
func (nrc *NopReadCloser) Read(buf []byte) (int, error) {
	return 0, io.EOF
}

func (nrc *NopReadCloser) Close() error {
	return nil
}

func newHTTPTransport(service OriginService, cfg OriginRequestConfig, log *zerolog.Logger) (*http.Transport, error) {
	originCertPool, err := tlsconfig.LoadOriginCA(cfg.CAPool, log)
	if err != nil {
		return nil, errors.Wrap(err, "Error loading cert pool")
	}

	httpTransport := http.Transport{
		Proxy:                 http.ProxyFromEnvironment,
		MaxIdleConns:          cfg.KeepAliveConnections,
		MaxIdleConnsPerHost:   cfg.KeepAliveConnections,
		IdleConnTimeout:       cfg.KeepAliveTimeout.Duration,
		TLSHandshakeTimeout:   cfg.TLSTimeout.Duration,
		ExpectContinueTimeout: 1 * time.Second,
		TLSClientConfig:       &tls.Config{RootCAs: originCertPool, InsecureSkipVerify: cfg.NoTLSVerify},
		ForceAttemptHTTP2:     cfg.Http2Origin,
	}
	if _, isHelloWorld := service.(*helloWorld); !isHelloWorld && cfg.OriginServerName != "" {
		httpTransport.TLSClientConfig.ServerName = cfg.OriginServerName
	}

	dialer := &net.Dialer{
		Timeout:   cfg.ConnectTimeout.Duration,

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Check the wrapped inner error to see whether the CA file was not found or failed to parse.
  2. Verify the CA pool path in your config exists and is readable by the cloudflared process.
  3. Ensure the file contains valid PEM-encoded certificates (e.g. Cloudflare origin ca root or your own CA).
  4. If your origin uses a publicly trusted cert, remove the custom CA pool setting so the system pool is used.

Example fix

// before (config.yml)
originRequest:
  caPool: /etc/cloudflared/origin-ca.pem   # file does not exist
// after
originRequest:
  caPool: /etc/cloudflared/certs/origin-ca.pem  # verify path & permissions
Defensive patterns

Strategy: validation

Validate before calling

func ensureCAPoolReadable(path string) error {
    if path == "" {
        return nil // system pool will be used
    }
    f, err := os.Open(path)
    if err != nil {
        return fmt.Errorf("caPool unreadable: %w", err)
    }
    defer f.Close()
    data, err := io.ReadAll(f)
    if err != nil {
        return err
    }
    if !bytes.Contains(data, []byte("BEGIN CERTIFICATE")) {
        return fmt.Errorf("caPool %s contains no PEM certificates", path)
    }
    return nil
}

Try / catch

if err := ensureCAPoolReadable(cfg.CAPool); err != nil {
    return fmt.Errorf("aborting: %w", err)
}
// then proceed with StartOrigins

Prevention

When it happens

Trigger: An origin request config with originServerName/CA pool set where cfg.CAPool points to a missing, unreadable, or malformed certificate file, causing tlsconfig.LoadOriginCA to fail.

Common situations: Wrong path to origin-ca-pool in config.yml, certificate file with wrong permissions, PEM file that is empty or corrupted, or forgetting to provision the CA file in a container image.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06). Data as JSON: /api/errors/57479940e3e5a69c. Report an issue: GitHub.