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

  1. Remove websocket.username and define the websocket credentials inside the users list instead
  2. Or remove the users/nkeys entries if single shared username auth is intended
  3. 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

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

Related errors


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