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
- Upgrade the Go toolchain used to build the server to 1.26 or later so FIPS mode supports websocket URLs, then rebuild
- Change the remote leaf node URL from ws:// or wss:// to nats:// or tls:// (plain leaf node connection)
- 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
- Keep separate config files for FIPS and non-FIPS builds
- Check runtime/Version and FIPS status at startup before loading leaf remotes
- Prefer tls:// leaf URLs unless websockets are required
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
- leaf nodes and gateways (both being defined) require a syste
- leafnode: %v
- invalid leafnode's minimum version: %v
- the minimum version should be at least 2.8.0
- can not have a single user/pass and a users array
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/5d1ffca161a9c4e8.
Report an issue: GitHub.