nats-io/nats-server · error

websocket: invalid header %q, "Sec-WebSocket-" prefix not al

Error message

websocket: invalid header %q, "Sec-WebSocket-" prefix not allowed

What it means

Custom websocket headers may not use the Sec-WebSocket-* prefix because those headers are negotiated by the WebSocket handshake protocol itself (Sec-WebSocket-Key, Sec-WebSocket-Accept, extensions, protocol, version). Allowing overrides would corrupt the handshake, so validation rejects any key starting with sec-websocket- (case-insensitive).

Source

Thrown at server/websocket.go:1191

	}
	if err := validatePinnedCerts(wo.TLSPinnedCerts); err != nil {
		return fmt.Errorf("websocket: %v", err)
	}

	// Check for invalid headers here.
	for key := range wo.Headers {
		k := strings.ToLower(key)
		switch k {
		case "host",
			"content-length",
			"connection",
			"upgrade",
			"nats-no-masking":
			return fmt.Errorf("websocket: invalid header %q not allowed", key)
		}

		if strings.HasPrefix(k, "sec-websocket-") {
			return fmt.Errorf("websocket: invalid header %q, \"Sec-WebSocket-\" prefix not allowed", key)
		}
	}

	return nil
}

// Creates or updates the existing map
func (s *Server) wsSetOriginOptions(o *WebsocketOpts) {
	ws := &s.websocket
	ws.mu.Lock()
	defer ws.mu.Unlock()
	// Copy over the option's same origin boolean
	ws.sameOrigin = o.SameOrigin
	// Reset the map. Will help for config reload if/when we support it.
	ws.allowedOrigins = nil
	if o.AllowedOrigins == nil {
		return
	}

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Remove the Sec-WebSocket-* header from websocket.headers
  2. Configure subprotocols on the client library (e.g. WebSocket constructor protocols argument), not server headers
  3. Rename the header to a non-reserved name if it is genuinely custom

Example fix

// before
websocket { headers: { "Sec-WebSocket-Protocol": "chat" } }
// after
websocket { headers: { "X-App-Protocol": "chat" } }
Defensive patterns

Strategy: validation

Validate before calling

for key := range opts.Websocket.Headers {
  if strings.HasPrefix(strings.ToLower(key), "sec-websocket-") {
    return fmt.Errorf("header %q uses reserved Sec-WebSocket- prefix", key)
  }
}

Prevention

When it happens

Trigger: websocket { headers: { "Sec-WebSocket-Protocol": "chat" } } or any header whose lowercase form begins with "sec-websocket-".

Common situations: Trying to force a subprotocol or WebSocket version via config headers instead of client-side options; copying request headers from a browser capture into server config.

Related errors


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