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
- Remove the Sec-WebSocket-* header from websocket.headers
- Configure subprotocols on the client library (e.g. WebSocket constructor protocols argument), not server headers
- 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
- Never mirror browser request headers into server handshake config
- Set subprotocols/versions on the client, not via server headers
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
- websocket: invalid header %q not allowed
- remote leaf node URL %q cannot be used in FIPS-140 mode when
- websocket authentication username not compatible with presen
- websocket authentication token not compatible with presence
- trusted operators or trusted keys configuration is required
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/d9852b1ecfcd8093.
Report an issue: GitHub.