goharbor/harbor · error
invalid CA certificate: no valid certificates found in PEM d
Error message
invalid CA certificate: no valid certificates found in PEM data
What it means
ValidateCACertificate in Harbor's common HTTP transport rejects a non-empty CA certificate string from which no valid x509 certificate could be parsed. normalizePEM first trims whitespace and normalizes line endings, then pem.Decode must find at least one block of type CERTIFICATE that x509.ParseCertificate accepts; zero parseable certificates triggers this error. Empty input is allowed (returns nil).
Source
Thrown at src/common/http/transport.go:125
return cert
}
// ValidateCACertificate validates whether the provided CA certificate string
// contains at least one valid PEM-encoded x509 certificate.
func ValidateCACertificate(caCert string) error {
caCert = normalizePEM(caCert)
if caCert == "" {
return nil
}
// Attempt to parse one or more certificates from the provided PEM
certs, err := parseCertificatesFromPEM(caCert)
if err != nil {
return fmt.Errorf("invalid CA certificate: %w", err)
}
if len(certs) == 0 {
return errors.New("invalid CA certificate: no valid certificates found in PEM data")
}
return nil
}
// parseCertificatesFromPEM decodes all PEM blocks and parses certificates.
func parseCertificatesFromPEM(pemData string) ([]*x509.Certificate, error) {
var certs []*x509.Certificate
rest := []byte(pemData)
for {
var block *pem.Block
block, rest = pem.Decode(rest)
if block == nil {
break
}
if block.Type != "CERTIFICATE" {
continueView on GitHub (pinned to 7b2fd08cc5)
Solutions
- Verify the PEM locally: openssl x509 -in ca.crt -noout -text — if that fails, the PEM is bad
- Convert DER to PEM: openssl x509 -inform der -in ca.der -out ca.pem
- Strip the TRUSTED marker: openssl x509 -in trusted.crt -out plain.crt
- Ensure the block reads -----BEGIN CERTIFICATE----- / -----END CERTIFICATE----- with intact base64, and paste only certificate(s), never a private key
Example fix
# before: DER file pasted as 'CA certificate' openssl x509 -inform der -in ca.der -out ca.pem # convert DER -> PEM openssl x509 -in ca.pem -noout -text # must print cert details # after: paste ca.pem's BEGIN/END CERTIFICATE block into the CA field
Defensive patterns
Strategy: validation
Validate before calling
// verify a CA PEM the same way Harbor does, before configuring it
func hasValidCertPEM(pemStr string) bool {
rest := []byte(strings.TrimSpace(pemStr))
found := false
for {
var block *pem.Block
block, rest = pem.Decode(rest)
if block == nil {
return found
}
if block.Type == "CERTIFICATE" {
if _, err := x509.ParseCertificate(block.Bytes); err != nil {
return false
}
found = true
}
}
} Prevention
- Always validate with openssl x509 -in ca.crt -noout -text before pasting a CA
- Export PEM, not DER, from certificate managers
- Never paste the PRIVATE KEY block into a CA certificate field
When it happens
Trigger: Supplying a CA certificate that is DER (binary), a private key or CSR only, an OpenSSL 'TRUSTED CERTIFICATE' block, a PEM with mangled BEGIN/END headers, base64 garbage, or only non-CERTIFICATE PEM blocks (e.g. just the key pair's PRIVATE KEY block).
Common situations: Copy-pasting the wrong half of a keypair into a registry or replication endpoint CA field, Windows line-ending or truncated pastes, certificates exported as DER from Windows certmgr.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- Error: The protocol is https but attribute ssl_cert is not s
- fail to ping LDAP server
- File {} not exist
- invalid {}
- key file {} permission is not 600
AI-assisted analysis of goharbor/harbor@7b2fd08cc5 (2026-08-16).
Data as JSON: /api/errors/9ec8476f3da16f23.
Report an issue: GitHub.