hashicorp/nomad · error

Failed to parse any valid certificates in CA file: %s

Error message

Failed to parse any valid certificates in CA file: %s

What it means

After reading CAFile, AppendCA feeds the bytes to pool.AppendCertsFromPEM, which returns false if not even one valid certificate could be parsed. Because PEM parsing is lenient and gives no detail, the library reports this opaque error naming the file. It means the CA file exists but contains no usable certificate.

Source

Thrown at helper/tlsutil/config.go:191

// AppendCA opens and parses the CA file and adds the certificates to
// the provided CertPool.
func (c *Config) AppendCA(pool *x509.CertPool) error {
	if c.CAFile == "" {
		return nil
	}

	// Read the file
	data, err := os.ReadFile(c.CAFile)
	if err != nil {
		return fmt.Errorf("Failed to read CA file: %v", err)
	}

	// Read certificates and return an error if no valid certificates were
	// found. Unfortunately it is very difficult to return meaningful
	// errors as PEM files are extremely permissive.
	if !pool.AppendCertsFromPEM(data) {
		return fmt.Errorf("Failed to parse any valid certificates in CA file: %s", c.CAFile)
	}

	return nil
}

// LoadKeyPair is used to open and parse a certificate and key file
func (c *Config) LoadKeyPair() (*tls.Certificate, error) {
	if c.CertFile == "" || c.KeyFile == "" {
		return nil, nil
	}

	if c.KeyLoader == nil {
		return nil, fmt.Errorf("No Keyloader object to perform LoadKeyPair")
	}

	cert, err := c.KeyLoader.LoadKeyPair(c.CertFile, c.KeyFile)
	if err != nil {
		return nil, fmt.Errorf("Failed to load cert/key pair: %v", err)

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Inspect the file: it must contain one or more '-----BEGIN CERTIFICATE-----' blocks (openssl x509 -in <file> -noout -text).
  2. Regenerate/re-download the CA bundle from the correct source and verify with openssl.
  3. Ensure you point CAFile at the CA certificate(s), not the private key or leaf cert chain only.
  4. Validate the whole bundle with openssl verify / openssl storeutl to catch malformed entries.

Example fix

// before
config.CAFile = "/etc/tls/server.key" // a private key, no certificates
// after
config.CAFile = "/etc/tls/ca.crt" // PEM certificate bundle
Defensive patterns

Strategy: validation

Validate before calling

func validateCABundle(path string) error {
    data, err := os.ReadFile(path)
    if err != nil { return err }
    if !x509.NewCertPool().AppendCertsFromPEM(data) {
        return fmt.Errorf("%s contains no valid PEM certificates", path)
    }
    return nil
}

Try / catch

tlsCfg, err := tlsConf.IncomingTLSConfig()
if err != nil && strings.Contains(err.Error(), "Failed to parse any valid certificates") {
    return fmt.Errorf("CA bundle at %s is not a PEM cert file: %w", cfg.CAFile, err)
}

Prevention

When it happens

Trigger: CAFile points to an existing readable file whose contents contain zero PEM blocks parseable as certificates — e.g. an empty file, a private key instead of a cert, plain text, HTML error page downloaded instead of a cert, or only unrelated PEM blocks.

Common situations: Downloading a CA bundle via curl that saved an error page; concatenating the wrong files; exporting a key instead of a certificate; config pointing at the client key file instead of the CA bundle; truncated copy/paste of the PEM.

Understand the failure class

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/1f02985664c54050. Report an issue: GitHub.