hashicorp/nomad · error

invalid certificate, %s not in %s

Error message

invalid certificate, %s not in %s

What it means

validateRaftTLS checks that the certificate presented on a raft-related RPC connection contains the expected name (e.g. server.<region>.nomad) in its CommonName or SAN DNS names. This error means the certificate is technically valid but does not cover the requested name, so the identity check fails.

Source

Thrown at nomad/rpc.go:163

// ValidateCertificateForName returns true if the RPC context certificate is valid
// for the given domain name.
func (ctx *RPCContext) ValidateCertificateForName(name string) error {
	if ctx == nil || !ctx.TLS {
		return nil
	}

	cert := ctx.Certificate()
	if cert == nil {
		return errors.New("missing certificate information")
	}

	validNames := []string{cert.Subject.CommonName}
	validNames = append(validNames, cert.DNSNames...)
	if slices.Contains(validNames, name) {
		return nil
	}

	return fmt.Errorf("invalid certificate, %s not in %s", name, strings.Join(validNames, ","))
}

func (ctx *RPCContext) IsStatic() bool {
	return ctx == nil
}

func (ctx *RPCContext) GetRemoteIP() (net.IP, error) {
	if ctx == nil {
		return nil, nil
	}
	var remoteAddr *net.TCPAddr
	var ok bool
	if ctx.Session != nil {
		remoteAddr, ok = ctx.Session.RemoteAddr().(*net.TCPAddr)
		if !ok {
			return nil, errors.New("session address was not a TCP address")
		}
	}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Re-issue the certificate including server.<region>.nomad in CN or DNS SANs for every region
  2. Regenerate certificates with the correct region name after adding/renaming a region
  3. Verify with `openssl x509 -text` that DNS names include the expected entry
  4. Update CA/certificate templates to include the region-scoped name pattern

Example fix

// before
openssl req -new -subj '/CN/client.nomad' ...
// after
openssl req -new -subj '/CN/server.us-east-1.nomad' -addext 'subjectAltName=DNS:server.us-east-1.nomad' ...
Defensive patterns

Strategy: validation

Validate before calling

out, _ := exec.Command("openssl", "x509", "-in", "server.pem", "-noout", "-text").Output()
expected := "server." + region + ".nomad"
if !strings.Contains(string(out), expected) {
    return fmt.Errorf("cert missing required SAN %s", expected)
}

Type guard

func certCoversName(cert *x509.Certificate, name string) bool {
    names := append([]string{cert.Subject.CommonName}, cert.DNSNames...)
    return slices.Contains(names, name)
}

Try / catch

if err != nil && strings.Contains(err.Error(), "invalid certificate") {
    return fmt.Errorf("re-issue certificate with SAN %s: %w", expectedName, err)
}

Prevention

When it happens

Trigger: A server presents a TLS certificate whose CN/DNS SANs do not include the name being validated (e.g. cert issued for server.region1.nomad used in region2), during validateRaftTLS-driven connection handling.

Common situations: Certificates issued without proper SAN entries for all regions; reusing one cert across regions; CA templates missing the server.<region>.nomad pattern after adding a new region.

Understand the failure class

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/95a832b3b6c00d87. Report an issue: GitHub.