hashicorp/nomad · error

failed to parse root certificate

Error message

failed to parse root certificate

What it means

Verify builds an x509.CertPool from caString; AppendCertsFromPEM returns false when none of the bytes decode as a certificate, so Verify reports the CA PEM could not be parsed and returns immediately without attempting chain verification.

Source

Thrown at helper/tlsutil/generate.go:349

			return nil, err
		}
		pk, ok := signer.(crypto.Signer)
		if !ok {
			return nil, fmt.Errorf("private key is not a valid format")
		}

		return pk, nil

	default:
		return nil, fmt.Errorf("unknown PEM block type for signing key: %s", block.Type)
	}
}

func Verify(caString, certString, dns string) error {
	roots := x509.NewCertPool()
	ok := roots.AppendCertsFromPEM([]byte(caString))
	if !ok {
		return fmt.Errorf("failed to parse root certificate")
	}

	cert, err := parseCert(certString)
	if err != nil {
		return fmt.Errorf("failed to parse certificate")
	}

	opts := x509.VerifyOptions{
		DNSName: fmt.Sprint(dns),
		Roots:   roots,
	}

	_, err = cert.Verify(opts)
	return err
}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Print/inspect the ca string or file and confirm it starts with '-----BEGIN CERTIFICATE-----'
  2. Regenerate or re-export the CA certificate in PEM encoding
  3. Verify the config path points to the CA bundle file, not the cert or key

Example fix

// before
certPool.AppendCertsFromPEM([]byte(keyPEM)) // wrong file: private key
// after
certPool.AppendCertsFromPEM([]byte(caPEM)) // must be CA certificate PEM
Defensive patterns

Strategy: validation

Validate before calling

func looksLikeCertPEM(s string) bool {
	block, _ := pem.Decode([]byte(s))
	if block == nil || block.Type != "CERTIFICATE" {
		return false
	}
	_, err := x509.ParseCertificate(block.Bytes)
	return err == nil
}
if !looksLikeCertPEM(caString) {
	return errors.New("CA bundle is not valid PEM certificate data")
}
err := tlsutil.Verify(caString, certString, dns)

Type guard

func isValidCA(ca string) bool {
	pool := x509.NewCertPool()
	return pool.AppendCertsFromPEM([]byte(ca))
}

Try / catch

if err := tlsutil.Verify(caPEM, certPEM, dns); err != nil {
	if err.Error() == "failed to parse root certificate" {
		return fmt.Errorf("CA bundle unreadable — verify ca config points at a PEM CA cert: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: Calling tlsutil.Verify(ca, cert, dns) where the ca argument is empty, truncated, contains only a private key, or is otherwise not PEM certificate data.

Common situations: Config value pointing at the wrong file (leaf cert or key instead of CA); missing newline/whitespace corruption after template rendering; CA supplied in DER format instead of PEM.

Understand the failure class

Related errors


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