nats-io/nats-server · error

leafnode: %v

Error message

leafnode: %v

What it means

This is a wrapping error emitted by validateLeafNode when validatePinnedCerts fails for the leafnode's TLSPinnedCerts. The original problem (an invalid pinned cert spec, e.g. malformed fingerprint or pubkey) is formatted as "leafnode: %v". It surfaces during Options validation whenever leaf node TLS pinned certificates are configured incorrectly.

Source

Thrown at server/leafnode.go:352

		if err := checkLeafMinVersionConfig(mv); err != nil {
			return err
		}
	}

	// The checks below will be done only when detecting that we are configured
	// with gateways. So if an option validation needs to be done regardless,
	// it MUST be done before this point!

	if o.Gateway.Name == _EMPTY_ && o.Gateway.Port == 0 {
		return nil
	}
	// If we are here we have both leaf nodes and gateways defined, make sure there
	// is a system account defined.
	if o.SystemAccount == _EMPTY_ {
		return fmt.Errorf("leaf nodes and gateways (both being defined) require a system account to also be configured")
	}
	if err := validatePinnedCerts(o.LeafNode.TLSPinnedCerts); err != nil {
		return fmt.Errorf("leafnode: %v", err)
	}
	return nil
}

func checkLeafMinVersionConfig(mv string) error {
	if ok, err := versionAtLeastCheckError(mv, 2, 8, 0); !ok || err != nil {
		if err != nil {
			return fmt.Errorf("invalid leafnode's minimum version: %v", err)
		} else {
			return fmt.Errorf("the minimum version should be at least 2.8.0")
		}
	}
	return nil
}

// Used to validate user names in LeafNode configuration.
// - rejects mix of single and multiple users.
// - rejects duplicate user names.

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Read the wrapped inner error (the %v) to see why the pinned cert is invalid
  2. Re-generate the pinned cert value, e.g. sha256 fingerprint of the peer cert, and paste it exactly (lowercase hex, no colons)
  3. Remove the tls_pinned_certs entries if pinning is not required
Defensive patterns

Strategy: validation

Validate before calling

for _, c := range opts.LeafNode.TLSPinnedCerts {
  if _, err := hex.DecodeString(c); err != nil || len(c) != 64 {
    return fmt.Errorf("bad pinned cert %q: %v", c, err)
  }
}

Prevention

When it happens

Trigger: validateOptions -> validateLeafNode runs and validatePinnedCerts(o.LeafNode.TLSPinnedCerts) returns an error, i.e. the leafnode block contains tls_pinned_certs entries that fail validation (bad hex digest, unsupported format, empty entries).

Common situations: Operators hand-copy SHA-256 fingerprints with typos/extra characters, or use a cert format not supported by the pinned-cert validator, when hardening leaf node TLS connections.

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/640fd0e5e7eb4283. Report an issue: GitHub.