nsqio/nsq · error
failed to AppendCertsFromPEM %s
Error message
failed to AppendCertsFromPEM %s
What it means
After successfully reading --http-client-tls-root-ca-file, nsqadmin seeds an x509.CertPool for its HTTPS client; if AppendCertsFromPEM returns false — the bytes were read but contain no parseable CERTIFICATE PEM block — startup fails with 'failed to AppendCertsFromPEM %s' naming the file. This is the parse-stage sibling of the read error: the file exists and is readable, but is not usable as PEM certificates.
Source
Thrown at nsqadmin/nsqadmin.go:79
InsecureSkipVerify: opts.HTTPClientTLSInsecureSkipVerify,
}
if opts.HTTPClientTLSCert != "" && opts.HTTPClientTLSKey != "" {
cert, err := tls.LoadX509KeyPair(opts.HTTPClientTLSCert, opts.HTTPClientTLSKey)
if err != nil {
return nil, fmt.Errorf("failed to LoadX509KeyPair %s, %s - %s",
opts.HTTPClientTLSCert, opts.HTTPClientTLSKey, err)
}
n.httpClientTLSConfig.Certificates = []tls.Certificate{cert}
}
if opts.HTTPClientTLSRootCAFile != "" {
tlsCertPool := x509.NewCertPool()
caCertFile, err := os.ReadFile(opts.HTTPClientTLSRootCAFile)
if err != nil {
return nil, fmt.Errorf("failed to read TLS root CA file %s - %s",
opts.HTTPClientTLSRootCAFile, err)
}
if !tlsCertPool.AppendCertsFromPEM(caCertFile) {
return nil, fmt.Errorf("failed to AppendCertsFromPEM %s", opts.HTTPClientTLSRootCAFile)
}
n.httpClientTLSConfig.RootCAs = tlsCertPool
}
for _, address := range opts.NSQLookupdHTTPAddresses {
_, err := net.ResolveTCPAddr("tcp", address)
if err != nil {
return nil, fmt.Errorf("failed to resolve --lookupd-http-address (%s) - %s", address, err)
}
}
for _, address := range opts.NSQDHTTPAddresses {
_, err := net.ResolveTCPAddr("tcp", address)
if err != nil {
return nil, fmt.Errorf("failed to resolve --nsqd-http-address (%s) - %s", address, err)
}
}
View on GitHub (pinned to 85cf10c09c)
Solutions
- Verify PEM parseability: 'openssl x509 -in <file> -noout -subject' (add -inform der and convert if it is DER: 'openssl x509 -inform der -in ca.der -out ca.pem').
- Inspect the file: 'grep -c "BEGIN CERTIFICATE" <file>' must be >= 1; look for stray whitespace/markers around the armor lines.
- Regenerate or re-copy the CA file from the source of truth and restart nsqadmin.
Example fix
# before nsqadmin --http-client-tls-root-ca-file=/etc/nsq/ca.der # failed to AppendCertsFromPEM /etc/nsq/ca.der # after openssl x509 -inform der -in /etc/nsq/ca.der -out /etc/nsq/ca.pem nsqadmin --http-client-tls-root-ca-file=/etc/nsq/ca.pem
Defensive patterns
Strategy: validation
Validate before calling
// pre-start: parse check mirroring nsqadmin's pool build
b, err := os.ReadFile(path)
if err != nil {
return err
}
if !x509.NewCertPool().AppendCertsFromPEM(b) {
return fmt.Errorf("%s contains no PEM certificates", path)
} Try / catch
if err := startNsqadmin(cfg); err != nil {
if strings.Contains(err.Error(), "failed to AppendCertsFromPEM") {
return errors.New("root CA file is not PEM; convert DER with: openssl x509 -inform der -in f -out f.pem")
}
return err
} Prevention
- Standardize on .pem extensions for all Go-facing TLS material.
- CI-validate CA bundles with AppendCertsFromPEM before shipping.
- Never let templates or humans hand-edit PEM armor.
When it happens
Trigger: The CA file is DER-encoded, is actually a key/CSR, has corrupted BEGIN/END armor or Base64, or is empty (empty files read fine and then fail here). Concatenated bundles are fine as long as every block is a valid CERTIFICATE.
Common situations: Internal PKI exports .crt as DER by convention while Go needs PEM; secrets rendered with template markers left in; file truncated by a size-limited config key; someone pointed the flag at the TLS key by accident.
Related errors
- failed to append certificate to pool
- failed to LoadX509KeyPair %s, %s - %s
- failed to read TLS root CA file %s - %s
- unknown tlsVersionOption %q
- failed to resolve --lookupd-http-address (%s) - %s
AI-assisted analysis of nsqio/nsq@85cf10c09c (2026-08-16).
Data as JSON: /api/errors/fa58276097e80c48.
Report an issue: GitHub.