nats-io/nats-server · error
gateway %q: %v
Error message
gateway %q: %v
What it means
Wraps a validatePinnedCerts failure for the gateway's TLSPinnedCerts, prefixed with the gateway's name. Pinned cert checks reject entries that are neither valid hex-encoded SHA-256 fingerprints nor valid base64 values, so gateway TLS pinning configuration is invalid.
Source
Thrown at server/gateway.go:328
if o.Gateway.Name == _EMPTY_ {
return errors.New("gateway has no name")
}
if strings.Contains(o.Gateway.Name, " ") {
return ErrGatewayNameHasSpaces
}
if o.Gateway.Port == 0 {
return fmt.Errorf("gateway %q has no port specified (select -1 for random port)", o.Gateway.Name)
}
for i, g := range o.Gateway.Gateways {
if g.Name == _EMPTY_ {
return fmt.Errorf("gateway in the list %d has no name", i)
}
if len(g.URLs) == 0 {
return fmt.Errorf("gateway %q has no URL", g.Name)
}
}
if err := validatePinnedCerts(o.Gateway.TLSPinnedCerts); err != nil {
return fmt.Errorf("gateway %q: %v", o.Gateway.Name, err)
}
return nil
}
// Computes a hash of 6 characters for the name.
// This will be used for routing of replies.
func getGWHash(name string) []byte {
return []byte(getHashSize(name, gwHashLen))
}
func getOldHash(name string) []byte {
sha := sha256.New()
sha.Write([]byte(name))
fullHash := []byte(fmt.Sprintf("%x", sha.Sum(nil)))
return fullHash[:4]
}
// Initialize the s.gateway structure. We do this even if the serverView on GitHub (pinned to 3a66a489d2)
Solutions
- Replace each pinned_certs entry with the full hex-encoded SHA-256 fingerprint of the certificate (64 hex chars)
- Or provide a valid base64-encoded value of the digest
- Trim whitespace/quotes from the config values and re-run nats-server -t to validate
- Verify the fingerprint with: openssl x509 -in cert.pem -noout -fingerprint -sha256
Example fix
// before
gateway { pinned_certs: ["/etc/certs/server.crt"] }
// after
gateway { pinned_certs: ["AB12CD34...98EF"] } # 64-char SHA-256 hex fingerprint Defensive patterns
Strategy: validation
Validate before calling
re := regexp.MustCompile(`^([0-9a-fA-F]{64}|[A-Za-z0-9+/=]+)$`)
for _, c := range opts.Gateway.TLSPinnedCerts {
if !re.MatchString(c) { return fmt.Errorf("bad pinned cert %q", c) }
} Try / catch
err := server.ValidateOptions(opts)
if err != nil && strings.Contains(err.Error(), "pinned") {
// fix the gateway pinned_certs entries, then retry
} Prevention
- Store SHA-256 hex fingerprints (64 chars), never file paths
- Generate fingerprints via openssl x509 -noout -fingerprint -sha256
- Trim whitespace and quotes from values in config tooling
- Validate gateway TLS config with nats-server -t before rollout
When it happens
Trigger: Options.Gateway.TLSPinnedCerts contains an entry that fails validatePinnedCerts (not 64-char hex, not valid base64) during gateway option validation at startup.
Common situations: Copying a certificate file path instead of the fingerprint into pinned_certs, truncated SHA-256 digests, whitespace/quotes around the value, or using SHA-1 fingerprints where SHA-256 is expected.
Related errors
- invalid chain link
- expected 'cert_store' to be a valid non-empty string
- expected 'cert_match_by' to be a valid non-empty string
- expected 'cert_match' to be a valid non-empty string
- gateway %q has no port specified (select -1 for random port)
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/b7776c879692c230.
Report an issue: GitHub.