nsqio/nsq · error

--http-client-tls-cert must be specified with --http-client-

Error message

--http-client-tls-cert must be specified with --http-client-tls-key

What it means

Mirror image of the missing-key case: opts.HTTPClientTLSKey is set while opts.HTTPClientTLSCert is empty, so the X509 key pair for nsqadmin's outbound HTTP client cannot be loaded and New() refuses to start. A TLS private key alone is never sufficient for client-certificate authentication.

Source

Thrown at nsqadmin/nsqadmin.go:57

	n := &NSQAdmin{
		notifications: make(chan *AdminAction),
	}
	n.swapOpts(opts)

	if len(opts.NSQDHTTPAddresses) == 0 && len(opts.NSQLookupdHTTPAddresses) == 0 {
		return nil, errors.New("--nsqd-http-address or --lookupd-http-address required")
	}

	if len(opts.NSQDHTTPAddresses) != 0 && len(opts.NSQLookupdHTTPAddresses) != 0 {
		return nil, errors.New("use --nsqd-http-address or --lookupd-http-address not both")
	}

	if opts.HTTPClientTLSCert != "" && opts.HTTPClientTLSKey == "" {
		return nil, errors.New("--http-client-tls-key must be specified with --http-client-tls-cert")
	}

	if opts.HTTPClientTLSKey != "" && opts.HTTPClientTLSCert == "" {
		return nil, errors.New("--http-client-tls-cert must be specified with --http-client-tls-key")
	}

	n.httpClientTLSConfig = &tls.Config{
		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",

View on GitHub (pinned to 85cf10c09c)

Solutions

  1. Add the certificate: --http-client-tls-cert=/etc/nsq/client.pem.
  2. Confirm the cert and key match: compare 'openssl x509 -noout -modulus' with 'openssl rsa -noout -modulus'.
  3. If mTLS is not actually required by the servers, remove both TLS client flags entirely.

Example fix

# before
nsqadmin --nsqd-http-address=10.0.0.1:4151 --http-client-tls-key=/etc/nsq/client.key
# after
nsqadmin --nsqd-http-address=10.0.0.1:4151 --http-client-tls-cert=/etc/nsq/client.pem --http-client-tls-key=/etc/nsq/client.key
Defensive patterns

Strategy: validation

Validate before calling

func validateClientTLSPair(cert, key string) error {
	if (cert == "") != (key == "") {
		return errors.New("--http-client-tls-cert and --http-client-tls-key must be set together")
	}
	if cert != "" {
		if _, err := tls.LoadX509KeyPair(cert, key); err != nil {
			return fmt.Errorf("preflight keypair check failed: %w", err)
		}
	}
	return nil
}

Prevention

When it happens

Trigger: Launching nsqadmin with --http-client-tls-key=/path/key.pem but no --http-client-tls-cert. The empty-string check fires before LoadX509KeyPair, so this is about a missing flag, not an unreadable or mismatched file.

Common situations: Secrets automation that injects only the key file; PEM bundles where the user assumed the certificate would be discovered automatically; renaming flags during upgrades leaving the cert flag behind.

Understand the failure class

Related errors


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