nats-io/nats-server · error
websocket authentication username not compatible with presen
Error message
websocket authentication username not compatible with presence of users/nkeys
What it means
The websocket block defines a single Username for authentication while the server options also define a Users (or Nkeys) list; the two auth mechanisms are mutually exclusive. The validator rejects this combination at startup because it would be ambiguous which credentials apply.
Source
Thrown at server/websocket.go:1162
}
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
// the user to be present.
if wo.NoAuthUser != _EMPTY_ {
if err := validateNoAuthUser(o, wo.NoAuthUser); err != nil {
return err
}
}
// Token/Username not possible if there are users/nkeys
if len(o.Users) > 0 || len(o.Nkeys) > 0 {
if wo.Username != _EMPTY_ {
return fmt.Errorf("websocket authentication username not compatible with presence of users/nkeys")
}
if wo.Token != _EMPTY_ {
return fmt.Errorf("websocket authentication token not compatible with presence of users/nkeys")
}
}
// Using JWT requires Trusted Keys
if wo.JWTCookie != _EMPTY_ {
if len(o.TrustedOperators) == 0 && len(o.TrustedKeys) == 0 {
return fmt.Errorf("trusted operators or trusted keys configuration is required for JWT authentication via cookie %q", wo.JWTCookie)
}
}
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)View on GitHub (pinned to 3a66a489d2)
Solutions
- Remove websocket.username and define the websocket credentials inside the users list instead
- Or remove the users/nkeys entries if single shared username auth is intended
- Prefer nkeys/accounts for multi-user setups and drop the legacy username
Example fix
// before
websocket { username: "svc" }
users: [{user: "a", password: "p"}]
// after
users: [{user: "a", password: "p"}]
// (websocket credentials come from the users list) Defensive patterns
Strategy: validation
Validate before calling
if opts.Websocket.Username != "" && (len(opts.Users) > 0 || len(opts.Nkeys) > 0) {
return fmt.Errorf("websocket.username conflicts with users/nkeys")
} Prevention
- Pick one auth model per server: single websocket username OR users/nkeys
- Keep auth config centralized in one block to avoid stale leftovers
When it happens
Trigger: Config contains websocket { username: "u" } (or authorization block referenced) together with top-level users: [...] or nkeys: [...] in the same options.
Common situations: Migrating from simple username auth to multi-user accounts without removing the websocket username; merging config fragments from different environments.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- websocket authentication token not compatible with presence
- remote leaf node URL %q cannot be used in FIPS-140 mode when
- trusted operators or trusted keys configuration is required
- websocket: invalid header %q not allowed
- websocket: invalid header %q, "Sec-WebSocket-" prefix not al
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/bcf359d41c23090d.
Report an issue: GitHub.