grpc/grpc-go · error
credentials: failed to append certificates
Error message
credentials: failed to append certificates
What it means
Returned by NewClientTLSFromFile in credentials/tls.go:290 when x509.CertPool.AppendCertsFromPEM returns false, meaning the file contents were not parseable as one or more PEM-encoded certificates. The file was readable (os.ReadFile succeeded) but the bytes are not a valid PEM cert block — e.g. a DER blob, a key file, or a non-cert PEM block.
Source
Thrown at credentials/tls.go:290
// NewClientTLSFromFile constructs TLS credentials from the provided root
// certificate authority certificate file(s) to validate server connections. If
// certificates to establish the identity of the client need to be included in
// the credentials (eg: for mTLS), use NewTLS instead, where a complete
// tls.Config can be specified.
//
// serverNameOverride is for testing only. If set to a non empty string, it will
// override the virtual host name of authority (e.g. :authority header field) in
// requests. Users should use grpc.WithAuthority passed to grpc.NewClient to
// override the authority of the client instead.
func NewClientTLSFromFile(certFile, serverNameOverride string) (TransportCredentials, error) {
b, err := os.ReadFile(certFile)
if err != nil {
return nil, err
}
cp := x509.NewCertPool()
if !cp.AppendCertsFromPEM(b) {
return nil, fmt.Errorf("credentials: failed to append certificates")
}
return NewTLS(&tls.Config{ServerName: serverNameOverride, RootCAs: cp}), nil
}
// NewServerTLSFromCert constructs TLS credentials from the input certificate for server.
func NewServerTLSFromCert(cert *tls.Certificate) TransportCredentials {
return NewTLS(&tls.Config{Certificates: []tls.Certificate{*cert}})
}
// NewServerTLSFromFile constructs TLS credentials from the input certificate file and key
// file for server.
func NewServerTLSFromFile(certFile, keyFile string) (TransportCredentials, error) {
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
return nil, err
}
return NewTLS(&tls.Config{Certificates: []tls.Certificate{cert}}), nil
}View on GitHub (pinned to 03255a9237)
Solutions
- Regenerate/obtain the certificate in PEM format (openssl x509 -inform DER -outform PEM -in cert.der -out cert.pem).
- Pass the CA certificate file (-----BEGIN CERTIFICATE-----), not the private key, to NewClientTLSFromFile.
- For a full tls.Config including client certs, use credentials.NewTLS with a populated tls.Config instead.
Example fix
// before
creds, err := credentials.NewClientTLSFromFile("/etc/certs/server.key", "svc") // wrong file
// after
creds, err := credentials.NewClientTLSFromFile("/etc/certs/ca.pem", "svc.example.com") Defensive patterns
Strategy: validation
Validate before calling
b, err := os.ReadFile(certFile)
if err != nil { return err }
pool := x509.NewCertPool()
if !pool.AppendCertsFromPEM(b) {
// likely DER or a non-cert PEM block; convert first
return errors.New("not PEM; convert with: openssl x509 -inform DER -outform PEM")
}
creds := credentials.NewClientTLSFromCert(pool, serverName) Type guard
func isPEMCert(b []byte) bool {
return bytes.Contains(b, []byte("-----BEGIN CERTIFICATE-----"))
} Try / catch
creds, err := credentials.NewClientTLSFromFile(certFile, serverName)
if err != nil {
if strings.Contains(err.Error(), "failed to append certificates") {
// file is not PEM certs; convert DER->PEM or point at the CA cert file
}
return err
} Prevention
- Keep CA certs in PEM (-----BEGIN CERTIFICATE-----) form, not DER.
- Do not pass private-key files to NewClientTLSFromFile.
- For client-cert mTLS, use credentials.NewTLS with a full tls.Config.
When it happens
Trigger: Passing a path to NewClientTLSFromFile whose content is a DER-encoded cert, a private key, a certificate chain in the wrong encoding, a CA bundle with extra text, or an empty file.
Common situations: Using the server key/cert file instead of the CA cert; cert generated as DER (openssl enc -outform DER) instead of PEM; pasting only the human-readable text of a PEM; an empty or truncated file from a failed download.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- credentials: failed to read the service account key file: %v
- credentials: no peer certificates found to verify authority
- pemfile: certificate and key file must be in the same direct
- provider instance is closed
- xds: CertificateProvider to fetch trusted roots is missing,
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/677d184490ee4be4.
Report an issue: GitHub.