hashicorp/nomad · error
first PEM-block should be CERTIFICATE type
Error message
first PEM-block should be CERTIFICATE type
What it means
The public ParseCert successfully decoded a PEM block, but its block.Type is not "CERTIFICATE" — the caller handed it a key, CSR, bundle starting with something else, or other PEM material. ParseCert only accepts a CERTIFICATE block as the first block.
Source
Thrown at helper/tlsutil/generate.go:292
if err != nil {
return nil, err
}
// String formatted
kID := sha256.Sum256(bs)
return kID[:], nil
}
// ParseCert parses the x509 certificate from a PEM-encoded value.
func ParseCert(pemValue string) (*x509.Certificate, error) {
// The _ result below is not an error but the remaining PEM bytes.
block, _ := pem.Decode([]byte(pemValue))
if block == nil {
return nil, fmt.Errorf("no PEM-encoded data found")
}
if block.Type != "CERTIFICATE" {
return nil, fmt.Errorf("first PEM-block should be CERTIFICATE type")
}
return x509.ParseCertificate(block.Bytes)
}
func parseCert(pemValue string) (*x509.Certificate, error) {
// The _ result below is not an error but the remaining PEM bytes.
block, _ := pem.Decode([]byte(pemValue))
if block == nil {
return nil, fmt.Errorf("no PEM-encoded data found")
}
if block.Type != "CERTIFICATE" {
return nil, fmt.Errorf("first PEM-block should be CERTIFICATE type")
}
return x509.ParseCertificate(block.Bytes)
}View on GitHub (pinned to 482b49bf1a)
Solutions
- Pass the certificate (-----BEGIN CERTIFICATE-----) content, not the key or CSR.
- If the PEM value is a combined bundle, split it and feed only the CERTIFICATE block to ParseCert (parseCert/ParseSigner handle the other halves).
- Double-check config wiring so CertFile content goes to cert parsing and KeyFile content to ParseSigner.
- If you have a CSR, get it signed (x509.CreateCertificate) before parsing.
Example fix
// before _, err := tlsutil.ParseCert(keyPEM) // key passed by mistake // after _, err := tlsutil.ParseCert(certPEM) _, err = tlsutil.ParseSigner(keyPEM)
Defensive patterns
Strategy: type-guard
Validate before calling
func firstBlockType(s string) string {
block, _ := pem.Decode([]byte(s))
if block == nil { return "" }
return block.Type
} Type guard
func isCertificateBlock(s string) bool {
block, _ := pem.Decode([]byte(s))
return block != nil && (block.Type == "CERTIFICATE" || block.Type == "X509 CERTIFICATE")
} Try / catch
if got := firstBlockType(pemValue); got != "CERTIFICATE" {
return fmt.Errorf("expected CERTIFICATE block, got %q", got)
}
cert, err := tlsutil.ParseCert(pemValue)
if err != nil { return err } Prevention
- Keep cert and key PEM values in separate config fields; never concatenate them for cert parsing.
- Check the BEGIN line of the first block before parsing.
- Route keys to ParseSigner and certificates to ParseCert.
- Verify provisioning pipelines store issued certs, not CSRs, in cert slots.
When it happens
Trigger: Calling ParseCert on a PEM private key (EC PRIVATE KEY / RSA PRIVATE KEY / PRIVATE KEY), a CSR (CERTIFICATE REQUEST), a CRL, or a cert chain where a key block precedes the certificate.
Common situations: Swapping cert and key config fields; concatenating key+cert into one value and passing it to ParseCert; using a CSR where a certificate is expected; clients submitting a certificate-signing request instead of the issued cert.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- no PEM-encoded data found
- no PEM-encoded data found
- Failed to parse any valid certificates in CA file: %s
- error encoding private key: %s
- unknown PEM block type for signing key: %s
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/96d5f1d8a38cd3dc.
Report an issue: GitHub.