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

  1. 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').
  2. Inspect the file: 'grep -c "BEGIN CERTIFICATE" <file>' must be >= 1; look for stray whitespace/markers around the armor lines.
  3. 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

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


AI-assisted analysis of nsqio/nsq@85cf10c09c (2026-08-16). Data as JSON: /api/errors/fa58276097e80c48. Report an issue: GitHub.