nats-io/nats-server · error

remote leaf node URL %q cannot be used in FIPS-140 mode when

Error message

remote leaf node URL %q cannot be used in FIPS-140 mode when built with this Go version, use Go 1.26 or later

What it means

When the server is built in FIPS-140 mode with a Go toolchain that lacks post-quantum/ML-KEM TLS support for websocket dialing, remote leaf node URLs using the websocket scheme (ws:// or wss://) are rejected at configuration validation time. The library throws this because FIPS builds before Go 1.26 cannot establish the required TLS connections to websocket leaf node remotes, so accepting them would fail at runtime. This is a startup-time Options validation in validateLeafNode.

Source

Thrown at server/leafnode.go:316

		}

		if len(rcfg.URLs) >= 2 {
			firstIsWS, ok := isWSURL(rcfg.URLs[0]), true
			for i := 1; i < len(rcfg.URLs); i++ {
				u := rcfg.URLs[i]
				if isWS := isWSURL(u); isWS && !firstIsWS || !isWS && firstIsWS {
					ok = false
					break
				}
			}
			if !ok {
				return fmt.Errorf("remote leaf node configuration cannot have a mix of websocket and non-websocket urls: %q", redactURLList(rcfg.URLs))
			}
		}
		if !wsAllowedFIPS() {
			for _, u := range rcfg.URLs {
				if isWSURL(u) {
					return fmt.Errorf("remote leaf node URL %q cannot be used in FIPS-140 mode when built with this Go version, use Go 1.26 or later", redactURLString(u.String()))
				}
			}
		}
		// Validate compression settings
		if rcfg.Compression.Mode != _EMPTY_ {
			if err := validateAndNormalizeCompressionOption(&rcfg.Compression, CompressionS2Auto); err != nil {
				return err
			}
		}
	}

	if o.LeafNode.Port == 0 {
		return nil
	}

	// If MinVersion is defined, check that it is valid.
	if mv := o.LeafNode.MinVersion; mv != _EMPTY_ {
		if err := checkLeafMinVersionConfig(mv); err != nil {

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Upgrade the Go toolchain used to build the server to 1.26 or later so FIPS mode supports websocket URLs, then rebuild
  2. Change the remote leaf node URL from ws:// or wss:// to nats:// or tls:// (plain leaf node connection)
  3. Disable FIPS-140 mode if websockets for leaf node remotes are a hard requirement

Example fix

// before
leafnodes {
  remotes = [
    { url: "wss://hub.example.com" }
  ]
}
// after
leafnodes {
  remotes = [
    { url: "tls://hub.example.com:7443" }
  ]
}
Defensive patterns

Strategy: validation

Validate before calling

for _, u := range opts.LeafNode.Remotes {
  for _, url := range u.URLs {
    if strings.HasPrefix(url, "ws://") || strings.HasPrefix(url, "wss://") {
      return fmt.Errorf("remote %q uses websocket URL; FIPS mode requires Go 1.26+", url)
    }
  }
}
return nil

Prevention

When it happens

Trigger: Starting a NATS server with FIPS-140 enabled (via fips build flag/mode) where a remote leaf node entry in leafnodes.remotes has a URL with ws:// or wss:// scheme, and the binary was built with a Go version earlier than 1.26 (wsAllowedFIPS() returns false).

Common situations: Compliance-driven deployments (government/regulated environments) that compile NATS with FIPS-140 mode and try to connect a leaf node over websockets through a load balancer or CDN that only exposes a WS endpoint; common after upgrading the NATS binary to a FIPS build while keeping the old config.

Related errors


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