nats-io/nats-server · error

websocket requires TLS configuration

Error message

websocket requires TLS configuration

What it means

The websocket block validation (websocket.go, options validation) enforces that a TLS configuration is provided unless NoTLS is explicitly set. Because plain websocket (ws://) without explicit opt-out is considered unsafe/misconfigured, the server refuses to start. FIPS builds with an older Go are rejected beforehand with a separate message.

Source

Thrown at server/websocket.go:1134

	if _, err := io.ReadFull(crand.Reader, p); err != nil {
		return _EMPTY_, err
	}
	return base64.StdEncoding.EncodeToString(p), nil
}

// Validate the websocket related options.
func validateWebsocketOptions(o *Options) error {
	wo := &o.Websocket
	// If no port is defined, we don't care about other options
	if wo.Port == 0 {
		return nil
	}
	if !wsAllowedFIPS() {
		return fmt.Errorf("websocket: cannot be used in FIPS-140 mode when built with this Go version, use Go 1.26 or later")
	}
	// Enforce TLS... unless NoTLS is set to true.
	if wo.TLSConfig == nil && !wo.NoTLS {
		return errors.New("websocket requires TLS configuration")
	}
	// Make sure that allowed origins, if specified, can be parsed.
	for _, ao := range wo.AllowedOrigins {
		u, err := url.ParseRequestURI(ao)
		if err != nil {
			return fmt.Errorf("unable to parse allowed origin: %v", err)
		}
		if u.Scheme != "http" && u.Scheme != "https" {
			return fmt.Errorf("unable to parse allowed origin %q: allowed origins must be absolute URLs with http or https scheme", ao)
		}
		if u.Host == _EMPTY_ {
			return fmt.Errorf("unable to parse allowed origin %q: host is required", ao)
		}
		if _, _, err := wsGetHostAndPort(u.Scheme == "https", u.Host); err != nil {
			return fmt.Errorf("unable to parse allowed origin: %v", err)
		}
	}
	// If there is a NoAuthUser, we need to have Users defined and

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Add a tls block (cert_file/key_file) under websocket {} to enable TLS
  2. If you intentionally want plain ws://, set `no_tls: true` in the websocket block
  3. When building Options in code, assign Websocket.TLSConfig or set Websocket.NoTLS = true
  4. If on FIPS mode with Go < 1.26, upgrade the build toolchain per the adjacent FIPS error

Example fix

// before (server.conf)
websocket {
  port: 8080
}
// after
websocket {
  port: 8080
  no_tls: true
}
Defensive patterns

Strategy: validation

Validate before calling

// before starting the server programmatically
func validateWebsocketOpts(wo *server.WebsocketOpts) error {
    if wo == nil || (wo.TLSConfig == nil && !wo.NoTLS) {
        return errors.New("websocket: set TLSConfig or NoTLS=true")
    }
    return nil
}

Prevention

When it happens

Trigger: Config contains a websocket {} block but no tls {} sub-block (TLSConfig is nil) and no `no_tls: true`; programmatic Options set Websocket without TLSConfig and leave NoTLS false.

Common situations: Dev setups intending plain ws:// but forgetting no_tls: true; TLS configured at an external proxy but not in NATS while no_tls wasn't set; copying a production config and removing the TLS block.

Understand the failure class

Related errors


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